/*
 * Copyright (c) 2018-2024 北京华恒盛世科技有限公司
 * QUICKPOOL is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
*/

#include <limits.h>

#include "common.h"
#include "limit.h"
#include "xdrbase.h"
#include "lib.h"

static unsigned int sizeof_resource_info(struct QuickPoolResourceInfo *);
static bool_t xdr_resource_info(XDR *, void *, struct header *, void *);
static bool_t xdr_resource_limit(XDR *, void *, struct header *, void *);
static bool_t xdr_resource_definition(XDR *, void *, struct header *, void *);
static bool_t xdr_cluster_info(XDR *, void *, struct header *, void *);
static bool_t xdr_queue_info(XDR *, void *, struct header *, void *);
static bool_t xdr_host_info(XDR *, void *, struct header *, void *);
static bool_t xdr_host_load(XDR *, void *, struct header *, void *);
static bool_t xdr_usergroup_info(XDR *, void *, struct header *, void *);
static bool_t xdr_hostgroup_info(XDR *, void *, struct header *, void *);
extern bool_t xdr_user_info(XDR *, void *, struct header *, void *);
static bool_t xdr_jobgroup(XDR *, void *, struct header *, void *);
static bool_t xdr_jobmsg(XDR *, void *, struct header *, void *);
static bool_t xdr_jobdep(XDR *, void *, struct header *, void *);
static bool_t xdr_jobinfo_array(XDR *, void *, struct header *, void *);

/**
 * @brief       XDR: xdr function to exchange quickpool information.
 *
 * @param[in|out]   xdrs     #1: xdrs for exchanging data
 * @param[in|out]   qpinfo   #2: basic cluster information to be exchanged
 * @param[in]       hdr      #3: XDR header
 * @param[in|out]   argument #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_quickpoolinfo(XDR *xdrs, void *qpinfo, struct header *hdr, void *argument)
{
    struct quickpoolInfo *info = (struct quickpoolInfo *)qpinfo;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        for (i=0; i<info->num_resources; i++) {
            gf_xdr_free(xdr_resource_definition, &(info->resource_table[i]));
        }

        FREEUP(info->resource_table);

        return TRUE;
    }

    if (!xdr_u_int(xdrs, &info->num_user_index) || !xdr_u_int(xdrs, &info->num_index)
        || !xdr_u_int(xdrs, &info->bool_start_index) || !xdr_u_int(xdrs, &info->string_start_index)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_index)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!xdr_u_int(xdrs, &info->num_resources)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_resources)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < info->num_resources) {

        info->resource_table = (struct resource_definition *)calloc(info->num_resources,
                                                                    sizeof(struct resource_definition));
        if(NULL == info->resource_table) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        info->num_resources*sizeof(struct resource_definition));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<info->num_resources; i++) {

        if (!gf_xdr_element(xdrs, (void *)&info->resource_table[i], hdr,
                            xdr_resource_definition, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__,
                        "gf_xdr_element(resource_table)", i);
            return FALSE;
        }
    }

    if (!xdr_u_int(xdrs, &info->num_types)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_types)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    char *sp;
    for (i=0; i<info->num_types; i++) {

        sp = info->host_types[i];
        if (XDR_DECODE == xdrs->x_op) {
            sp[0] = '\0';
        }

        if (!gf_xdr_string(xdrs, &sp, hdr, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_string(host_types)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (!xdr_u_int(xdrs, &info->num_models)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_models)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    for (i=0; i<info->num_models; i++) {

        sp = info->host_models[i];
        if (XDR_DECODE == xdrs->x_op) {
            sp[0] = '\0';
        }

        if (!gf_xdr_string(xdrs, &sp, hdr, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_string(host_models)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }

        if (!xdr_float(xdrs, &info->cpu_factor[i])) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_float(cpu_factor)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }

        sp = info->host_archs[i];
        if (XDR_DECODE == xdrs->x_op) {
            sp[0] = '\0';
        }

        if (!gf_xdr_string(xdrs, &sp, hdr, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_string(host_archs)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    return TRUE;
} // end function libxdr_quickpoolinfo

/**
 * @brief       XDR: xdr function to exchange parameter settings.
 *
 * @param[in|out]   xdrs     #1: xdrs for exchanging data
 * @param[in|out]   settings #2: parameter settings to be exchanged
 * @param[in]       hdr      #3: XDR header
 * @param[in|out]   argument #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_setting(XDR *xdrs, void *settings, struct header *hdr, void *argument)
{
    struct QuickPoolParameter *paramconf = (struct QuickPoolParameter *)settings;

    if (XDR_FREE == xdrs->x_op) {

        if (NULL == paramconf) {
            return TRUE;
        }

        free_param_value(paramconf->param);
        paramconf->number = 0;

        return TRUE;
    }

    if (!xdr_u_int(xdrs, &paramconf->number)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(number)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < paramconf->number) {

        // add 1 for tail of the parameter setting, it is useful for free.
        paramconf->param = (struct config_param *)calloc(paramconf->number+1,
                                                         sizeof(struct config_param));
        if (NULL == paramconf->param) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", (paramconf->number+1)*sizeof(struct config_param));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
	}
    }

    unsigned int i;
    for (i=0; i<paramconf->number; i++) {

        if (!(gf_xdr_string(xdrs, &paramconf->param[i].param_name, hdr, NULL)
              && xdr_int(xdrs, (int *)(&paramconf->param[i].param_type))
              && xdr_int(xdrs, &paramconf->param[i].index))) {

            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(param_name)");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }

        switch (paramconf->param[i].param_type) {
        case INT_PARAM:
            if (!xdr_int(xdrs, &paramconf->param[i].int_value)) {
                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(int_value)");
                quickpool_errno = ERROR_XDR;
                return FALSE;
            }
            break;
        case BOOL_PARAM:
            if (!xdr_int(xdrs, &paramconf->param[i].bool_value)) {
                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(bool_value)");
                quickpool_errno = ERROR_XDR;
                return FALSE;
            }
            break;
        case STRING_PARAM:
            if (!gf_xdr_string(xdrs, &paramconf->param[i].string_value, hdr, NULL)) {
                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(string_value)");
                quickpool_errno = ERROR_XDR;
                return FALSE;
            }
            break;
        case FLOAT_PARAM:
            if (!xdr_double(xdrs, &paramconf->param[i].float_value)) {
                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_double(float_value)");
                quickpool_errno = ERROR_XDR;
                return FALSE;
            }
            break;
        }
    }

    if (XDR_DECODE == xdrs->x_op && 0 < paramconf->number) { // tail
        paramconf->param[paramconf->number].param_name = NULL;
        paramconf->param[paramconf->number].param_type = STRING_PARAM;
    }

    return TRUE;
} // end function libxdr_setting

/**
 * @brief       Calculate size of resource reply.
 *
 * @param[in]   reply         #1: resource reply
 *
 * @retval      >0            #1: size of resource reply
 */
unsigned int
sizeof_resource_reply(struct QuickPoolResourceReply *reply)
{
    unsigned int len, i;

    len = sizeof(struct QuickPoolResourceReply);

    len += sizeof(int);
    for (i = 0; i < reply->num_resources; i++) {
        len += sizeof_resource_info(&(reply->resources[i]));
    }

    len += sizeof(int) + strlen(reply->error_message) + XDR_OFFSET;

    return len;
} // end function sizeof_resource_reply

/**
 * @brief       XDR: xdr function to exchange resource information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   resourcereply   #2: number of resources and their information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_resource_reply(XDR *xdrs, void *resourcereply, struct header *hdr, void *argument)
{
    struct QuickPoolResourceReply *reply = (struct QuickPoolResourceReply *)resourcereply;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        for (i=0; i<reply->num_resources; i++) {
            gf_xdr_free(xdr_resource_info, &(reply->resources[i]));
        }
        FREEUP(reply->resources);

        return TRUE;
    }

    if (!(xdr_u_int(xdrs, &reply->num_resources))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(numResources)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_resources) {

        reply->resources = (struct QuickPoolResourceInfo *)calloc(reply->num_resources,
                                                                  sizeof(struct QuickPoolResourceInfo));
        if (NULL == reply) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        reply->num_resources*sizeof(struct QuickPoolResourceInfo));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<reply->num_resources; i++) {

        if (!gf_xdr_element(xdrs, (void *)&reply->resources[i], hdr, xdr_resource_info, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(resources)", i);
            if (XDR_DECODE == xdrs->x_op) {
                reply->num_resources = i;
            }

            return FALSE;
        }
    }

    char *sp = reply->error_message;
    if (!gf_xdr_string(xdrs, &(sp), hdr, NULL)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(error_message)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    return TRUE;
} // end function libxdr_resource_reply

/**
 * @brief       XDR: xdr function to exchange cluster information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   clusterreply    #2: number of clusters and their information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_clusterinfo_reply(XDR *xdrs, void *clusterreply, struct header *hdr, void *argument)
{
    struct QuickPoolClusterReply *reply = (struct QuickPoolClusterReply *)clusterreply;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        for (i=0; i<reply->num_clusters; i++) {
            gf_xdr_free(xdr_cluster_info, &(reply->clusters[i]));
        }
        FREEUP(reply->clusters);

        return TRUE;
    }

    if (!xdr_u_int(xdrs, &(reply->num_clusters))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_clusters)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_clusters) {

        reply->clusters = (struct QuickPoolClusterInfo *)calloc(reply->num_clusters,
                                                                sizeof(struct QuickPoolClusterInfo));
        if (NULL == reply->clusters) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        reply->num_clusters*sizeof(struct QuickPoolClusterInfo));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<reply->num_clusters; i++) {

        if (!gf_xdr_element(xdrs, (void *)&(reply->clusters[i]), hdr, xdr_cluster_info, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(clusters)", i);
            if (XDR_DECODE == xdrs->x_op) {
                reply->num_clusters = i;
            }

            return FALSE;
        }
    }

    return TRUE;
} // end function libxdr_clusterinfo_reply

/**
 * @brief       Calculate size of queue reply.
 *
 * @param[in]   reply         #1: queue reply
 *
 * @retval      >0            #1: size of queue reply
 */
unsigned int
sizeof_queueinfo_reply(struct QuickPoolQueueReply *reply, unsigned int numindex)
{
    unsigned int len = 0;

    unsigned int i;
    for (i=0; i<reply->num_queue; i++) {
        len += strlen(reply->queues[i].description)
               + strlen(reply->queues[i].users)
               + strlen(reply->queues[i].hosts)
               + strlen(reply->queues[i].run_window)
               + strlen(reply->queues[i].dispatch_window)
               + strlen(reply->queues[i].administrators)
               + strlen(reply->queues[i].prejob_command)
               + strlen(reply->queues[i].postjob_command)
               + strlen(reply->queues[i].prepost_user)
               + strlen(reply->queues[i].requeue_exitcode)
               + strlen(reply->queues[i].resource_requirement)
               + strlen(reply->queues[i].resume_condition)
               + strlen(reply->queues[i].stop_condition)
               + strlen(reply->queues[i].job_starter)
               + strlen(reply->queues[i].suspend_command)
               + strlen(reply->queues[i].resume_command)
               + strlen(reply->queues[i].terminate_command)
               + strlen(reply->queues[i].chkpnt_dir)
               + strlen(reply->queues[i].preemption);

        if (0 < reply->queues[i].num_fairshare_account) {
            len = len + reply->queues[i].num_fairshare_account
                  * (sizeof(struct share_acct) + MAXNAMELEN);
        }
    }

    len += sizeof(struct QuickPoolQueueReply)
           + reply->num_queue * (sizeof(struct QuickPoolQueueInfo)
           + MAXNAMELEN + numindex * 2 * sizeof(float))
           + reply->num_queue * sizeof(int);

    return len;
} // end function sizeof_queueinfo_reply

/**
 * @brief       XDR: xdr function to exchange queue information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   queuereply      #2: number of queues and their information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_queue_reply(XDR *xdrs, void *queuereply, struct header *hdr, void *argument)
{
    struct QuickPoolQueueReply *reply = (struct QuickPoolQueueReply *)queuereply;
    unsigned int *numIndicies = (unsigned int *)argument;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        for (i=0; i<reply->num_queue; i++) {
            gf_xdr_free(xdr_queue_info, &(reply->queues[i]));
        }
        FREEUP(reply->queues);

        return TRUE;
    }

    if (!(xdr_u_int(xdrs, &(reply->num_queue))
          && xdr_u_int(xdrs, numIndicies))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_queue)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_queue) {

        reply->queues = (struct QuickPoolQueueInfo *)calloc(reply->num_queue,
                                                            sizeof(struct QuickPoolQueueInfo));
        if (NULL == reply->queues) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", reply->num_queue*sizeof(struct QuickPoolQueueInfo));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<reply->num_queue; i++) {

        if (!gf_xdr_element(xdrs, &(reply->queues[i]), hdr, xdr_queue_info, numIndicies)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__,
                        "gf_xdr_element(queues)", i);
            if (XDR_DECODE == xdrs->x_op) {
                reply->num_queue = i;
            }

            return FALSE;
        }
    }

    return TRUE;
} // end function libxdr_queue_reply

/**
 * @brief       XDR: xdr function to exchange host information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   hostreply       #2: number of hosts and their information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_host_reply(XDR *xdrs, void *hostreply, struct header *hdr, void *argument)
{
    unsigned int i;
    struct QuickPoolHostReply *reply = (struct QuickPoolHostReply *)hostreply;
    unsigned int *numIndicies = (unsigned int *)argument;

    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        for (i = 0; i < reply->num_hosts; i++) {
            gf_xdr_free(xdr_host_info, &(reply->hosts[i]));
        }
        FREEUP(reply->hosts);

        return TRUE;
    }

    if (!xdr_u_int(xdrs, &reply->num_hosts)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_hosts)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (NULL != numIndicies) {
        if (!xdr_u_int(xdrs, numIndicies)) {
            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "numIndicies)");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_hosts) {
        reply->hosts = (struct QuickPoolHostInfo *)calloc(reply->num_hosts,
                                                          sizeof(struct QuickPoolHostInfo));
        if (NULL == reply->hosts) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        reply->num_hosts*sizeof(struct QuickPoolHostInfo));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i = 0; i < reply->num_hosts; i++) {

        if (!gf_xdr_element(xdrs, &(reply->hosts[i]), hdr, xdr_host_info, numIndicies)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(hosts)", i);
            if (XDR_DECODE == xdrs->x_op) {
                reply->num_hosts = i;
            }

            return FALSE;
        }
    }

    return TRUE;
} // end function libxdr_host_reply

/**
 * @brief       XDR: xdr function to exchange node load.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   loadreply       #2: number of hosts and their load to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_load_reply(XDR *xdrs, void *loadreply, struct header *hdr, void *argument)
{
    unsigned int i;
    struct QuickPoolHostLoadReply *reply = (struct QuickPoolHostLoadReply *)loadreply;

    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        for (i=0; i<reply->num_hosts; i++) {
            gf_xdr_free(xdr_host_load, &(reply->host_load[i]));
        }
        FREEUP(reply->host_load);

        for (i=0; i<reply->num_index; i++) {
            FREEUP(reply->indicies[i]);
        }
        FREEUP(reply->indicies);

        return TRUE;
    }

    if (!(xdr_u_int(xdrs, &reply->num_hosts) && xdr_u_int(xdrs, &reply->num_index))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_hosts)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_index) {

        reply->indicies = (char **)calloc(reply->num_index, sizeof(char *));
        if (NULL == reply->indicies) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        reply->num_index*sizeof(char *));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i < reply->num_index; i++) {

        if (!(gf_xdr_string(xdrs, &(reply->indicies[i]), hdr, NULL))) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_string(indicies)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_hosts) {

        reply->host_load = (struct QuickPoolHostLoad *)calloc(reply->num_hosts,
                                                              sizeof(struct QuickPoolHostLoad));
        if (NULL == reply->host_load) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        reply->num_hosts*sizeof(struct QuickPoolHostLoad));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i = 0; i < reply->num_hosts; i++) {

        if (!gf_xdr_element(xdrs, &(reply->host_load[i]), hdr, xdr_host_load, &reply->num_index)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(load)", i);
            if (XDR_DECODE == xdrs->x_op) {
                reply->num_hosts = i;
            }

            return FALSE;
        }
    }

    return TRUE;
} // end function libxdr_load_reply

/**
 * @brief       Calculate size of group reply.
 *
 * @param[in]   options       #1: HOST_GRP or USER_GRP
 * @param[in]   groups        #2: group reply
 *
 * @retval      >0            #1: size of queue reply
 */
unsigned int
sizeof_groupinfo_reply(int options, void *groups)
{
    unsigned int len=0;
    unsigned int i, j;

    if (options & HOST_GRP) {
        struct QuickPoolHostGroupReply *hg = (struct QuickPoolHostGroupReply *)groups;

        len = sizeof(struct QuickPoolHostGroupReply);
        len += hg->num_groups * sizeof(struct QuickPoolHostGroupInfo);
        len += hg->num_groups * sizeof(int);

        for (i=0; i<hg->num_groups; i++) {
            struct QuickPoolHostGroupInfo *ent;

            ent = &(hg->groups[i]);

            len += sizeof(struct QuickPoolHostGroupInfo);
            len += strlen(ent->group_name) + 1;

            len += sizeof(struct nameList);
            if (NULL != ent->member_list) {
                len += sizeof(int);
                for (j=0; j<ent->member_list->num_name; j++) {
                    len += strlen(ent->member_list->names[j]) + 1 + sizeof(int) + XDR_OFFSET;
                }
            }

            if (NULL != ent->exclude_members) {
                len += strlen(ent->exclude_members) + 1 + sizeof(int) + XDR_OFFSET;
            }
            len += sizeof(int);
        }
    } else {
        struct QuickPoolUserGroupReply *ug = (struct QuickPoolUserGroupReply *)groups;

        len = sizeof(struct QuickPoolUserGroupReply);
        len += ug->num_groups * sizeof(struct QuickPoolUserGroupInfo);
        len += ug->num_groups * sizeof(int);

        for (i=0; i<ug->num_groups; i++) {
            struct QuickPoolUserGroupInfo *ent;

            ent = &(ug->groups[i]);

            len += sizeof(struct QuickPoolUserGroupInfo);
            len += strlen(ent->group_name) + 1 + XDR_OFFSET;

            len += sizeof(struct nameList);
            if (NULL != ent->member_list) {
                len += sizeof(int);
                for (j=0; j<ent->member_list->num_name; j++) {
                    len += strlen(ent->member_list->names[j]) + 1 + sizeof(int) + XDR_OFFSET;
                }
            }

            if (NULL != ent->user_shares) {
                len += strlen(ent->user_shares) + 1 + sizeof(int) + XDR_OFFSET;
            }

            if (NULL != ent->exclude_members) {
                len += strlen(ent->exclude_members) + 1 + sizeof(int) + XDR_OFFSET;
            }
        }
    }

    return(len);
} // end function sizeof_groupinfo_reply

/**
 * @brief       XDR: xdr function to exchange user group.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   groupreply      #2: number of user group and
 *                                      their information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_usergroup_reply(XDR *xdrs, void *groupreply, struct header *hdr, void *argument)
{
    struct QuickPoolUserGroupReply *reply = (struct QuickPoolUserGroupReply *)groupreply;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        for (i = 0; i < reply->num_groups; i++) {
            gf_xdr_free(xdr_usergroup_info, &(reply->groups[i]));
        }

        FREEUP(reply->groups);
        reply->num_groups = 0;

        return TRUE;
    }

    if (!xdr_u_int(xdrs, &(reply->num_groups))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_groups)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_groups) {

        reply->groups = (struct QuickPoolUserGroupInfo *)calloc(reply->num_groups,
                                                                sizeof(struct QuickPoolUserGroupInfo));
        if (NULL == reply->groups) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        reply->num_groups*sizeof(struct QuickPoolUserGroupInfo));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i = 0; i < reply->num_groups; i++) {

        if (!gf_xdr_element(xdrs, &(reply->groups[i]), hdr, xdr_usergroup_info, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(groups)", i);
            if (XDR_DECODE == xdrs->x_op) {
                reply->num_groups = i;
            }

            return FALSE;
        }
    }

    return TRUE;
} // end function libxdr_usergroup_reply

/**
 * @brief       XDR: xdr function to exchange host group.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   groupreply      #2: number of host group and
 *                                      their information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_hostgroup_reply(XDR *xdrs, void *groupreply, struct header *hdr, void *argument)
{
    struct QuickPoolHostGroupReply *reply = (struct QuickPoolHostGroupReply *)groupreply;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        for (i=0; i<reply->num_groups; i++) {
            gf_xdr_free(xdr_hostgroup_info, &(reply->groups[i]));
        }
        FREEUP(reply->groups);
        reply->num_groups = 0;

        return TRUE;
    }

    if (!xdr_u_int(xdrs, &(reply->num_groups))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_groups)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_groups) {

        reply->groups = (struct QuickPoolHostGroupInfo *)calloc(reply->num_groups,
                                                                sizeof(struct QuickPoolHostGroupInfo));
        if (NULL == reply->groups) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        reply->num_groups*sizeof(struct QuickPoolHostGroupInfo));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<reply->num_groups; i++) {

        if (!gf_xdr_element(xdrs, &(reply->groups[i]), hdr, xdr_hostgroup_info, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(groups)", i);
            if (XDR_DECODE == xdrs->x_op) {
                reply->num_groups = i;
            }

            return FALSE;
        }
    }

    return TRUE;
} // end function libxdr_hostgroup_reply

/**
 * @brief       XDR: xdr function to exchange user information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   userreply       #2: number of user and
 *                                      their information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_user_reply(XDR *xdrs, void *userreply, struct header *hdr, void *argument)
{
    struct  QuickPoolUserReply *reply = (struct QuickPoolUserReply *)userreply;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        for (i=0; i<reply->num_user; i++) {
            gf_xdr_free(xdr_user_info, &(reply->users[i]));
        }
        FREEUP(reply->users);

        return TRUE;
    }

    if (!xdr_u_int(xdrs, &(reply->num_user))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_user)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_user) {

        reply->users = (struct QuickPoolUserInfo *)calloc(reply->num_user,
                                                          sizeof(struct QuickPoolUserInfo));
        if (NULL == reply->users) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        reply->num_user*sizeof(struct QuickPoolUserInfo));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<reply->num_user; i++ ) {

        if (!gf_xdr_element(xdrs, &(reply->users[i]), hdr, xdr_user_info, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(users)", i);
            if (XDR_DECODE == xdrs->x_op) {
                reply->num_user = i;
            }

            return FALSE;
        }
    }

    return TRUE;
} // end function libxdr_user_reply

/**
 * @brief       XDR: xdr function to exchange job submit reply header.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   submitreply     #2: job submit reply
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_submit_reply(XDR *xdrs, void *submitreply, struct header *hdr, void *argument)
{
    struct QuickPoolSubmitReply *reply = (struct QuickPoolSubmitReply *)submitreply;

    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }
        FREEUP(reply->queue);

        return TRUE;
    }

    if (!xdr_jobID(xdrs, (void *)&(reply->jobid), hdr, argument)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_jobID");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!gf_xdr_string(xdrs, &(reply->queue), hdr, NULL)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(queue)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    char *strErrMsg = reply->error_message;
    if (!gf_xdr_string(xdrs, &strErrMsg, hdr, NULL)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(error_message)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    return TRUE;
} // end function libxdr_submit_reply

/**
 * @brief       XDR: xdr function to exchange job reply header.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   jobreply        #2: number of jobs, number of error
 *                                      and host names to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_job_reply(XDR *xdrs, void *jobreply, struct header *hdr, void *argument)
{
    struct QuickPoolJobReply *reply = (struct QuickPoolJobReply *)jobreply;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        FREEUP(reply->jobIDs);
        for (i=0; i<reply->num_node; i++) {
            FREEUP(reply->node_names[i]);
        }
        FREEUP(reply->node_names);

        for (i=0; i<reply->num_error; i++) {
            FREEUP(reply->error_messages[i]);
        }
        FREEUP(reply->error_messages);

        return TRUE;
    }

    if (!(xdr_u_int(xdrs, &(reply->num_job)) && xdr_u_int(xdrs, &(reply->num_node)))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_job)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_job) {

        reply->jobIDs = (JOBID_T *)calloc(reply->num_job, sizeof(JOBID_T));
        if (NULL == reply->jobIDs) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", reply->num_job*sizeof(JOBID_T));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<reply->num_job; i++) {

        if (!xdr_jobID(xdrs, (void *)&(reply->jobIDs[i]), hdr, argument)) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_jobID", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_node) {

        reply->node_names = (char **)calloc(reply->num_node, sizeof(char *));
        if (NULL == reply->node_names) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", reply->num_node*sizeof(char *));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i = 0; i < reply->num_node; i++) {

        if (!(gf_xdr_string(xdrs, &(reply->node_names[i]), hdr, NULL))) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_string(node_name)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (!(xdr_u_int(xdrs, &(reply->num_error)))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_error)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_error) {

        reply->error_messages = (char **)calloc(reply->num_error, sizeof(char *));
        if (NULL == reply->error_messages) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", reply->num_error*sizeof(char *));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i = 0; i < reply->num_error; i++) {

        if (!(gf_xdr_string(xdrs, &(reply->error_messages[i]), hdr, NULL))) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_string(errmsg)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    return TRUE;
} // end function libxdr_job_reply

void
free_job_usednuma(unsigned int numnode, struct jobInfoNuma *usednuma)
{
    if (NULL == usednuma) {
        return;
    }

    unsigned int i;
    for (i = 0; i < numnode; i++) {
        gf_list_free(usednuma->alloc_job_numa[i].used_numa, NULL);
    }
    FREEUP(usednuma->alloc_job_numa);
    FREEUP(usednuma);

    return;
} // end function free_job_usednuma

void
free_job_usedgpu(unsigned int numnode, struct jobInfoGPU *usedgpu)
{
    if (NULL == usedgpu) {
        return;
    }

    unsigned int i;
    for (i = 0; i < numnode; i++) {

        unsigned int j;
        for (j=0; j<usedgpu->alloc_job_gpu[i].num_gpu; j++) {
            FREEUP(usedgpu->alloc_job_gpu[i].gpus[j].model);
        }
        FREEUP(usedgpu->alloc_job_gpu[i].gpus);
    }

    FREEUP(usedgpu->alloc_job_gpu);
    FREEUP(usedgpu);

    return;
} // end function free_job_usedgpu

/**
 * @brief       Calculate size of job information reply to client.
 *
 * @param[in]   jobinfo       #1: job information
 *
 * @retval      >0            #1: size of job information
 */
unsigned int
sizeof_quickpool_jobinfo(struct QuickPoolJobInfo *jobinfo, unsigned int numindex)
{
    unsigned int len;

    len = sizeof(struct QuickPoolJobInfo);
    len += jobinfo->num_pending_reason * sizeof(int);
    len += jobinfo->num_execute_node * MAXHOSTNAMELEN;
    len += 2 * numindex * sizeof(float);
    len += MAXNAMELEN;
    if (NULL != jobinfo->execute_user) {
        len += strlen(jobinfo->execute_user) + 1;
        len += sizeof(int);
    }
    if (NULL != jobinfo->execute_homedir) {
        len += strlen(jobinfo->execute_homedir) + 1;
        len += sizeof(int);
    }
    if (NULL != jobinfo->execute_cwd) {
        len += strlen(jobinfo->execute_cwd) + 1;
        len += sizeof(int);
    }

    len += sizeof(struct submitRequest);
    if (NULL != jobinfo->submit->job_name) {
        len += strlen(jobinfo->submit->job_name) + 1;
        len += sizeof(int);
    }
    len += strlen(jobinfo->submit->queue) + 1;
    len += sizeof(int);

    unsigned int i;
    for (i=0; i<jobinfo->submit->num_spec_node; i++) {
        len += strlen(jobinfo->submit->spec_nodes[i]) + 1;
        len += sizeof(int);
    }
    if (NULL != jobinfo->submit->resource_requirement) {
        len += strlen(jobinfo->submit->resource_requirement) + 1;
        len += sizeof(int);
    }
    len += MAXHOSTNAMELEN;
    if (NULL != jobinfo->submit->dependency) {
        len += strlen(jobinfo->submit->dependency) + 1;
    }
    len += PATH_MAX;
    len += PATH_MAX;
    len += PATH_MAX;
    len += PATH_MAX;
    len += strlen(jobinfo->submit->command) + 1;
    len += sizeof(int);
    len += PATH_MAX;
    len += jobinfo->submit->num_exec_files * sizeof(struct execution_file);
    len += PATH_MAX;
    len += MAXHOSTNAMELEN;
    len += PATH_MAX;
    if (NULL != jobinfo->submit->prejob_command) {
        len += strlen(jobinfo->submit->prejob_command) + 1;
        len += sizeof(int);
    }
    if (NULL != jobinfo->submit->postjob_command) {
        len += strlen(jobinfo->submit->postjob_command) + 1;
        len += sizeof(int);
    }      
    if (NULL != jobinfo->submit->mail_user) {
        len += strlen(jobinfo->submit->mail_user) + 1;
        len += sizeof(int);
    }
    if (NULL != jobinfo->submit->project) {
        len += strlen(jobinfo->submit->project) + 1;
        len += sizeof(int);
    }
    if (NULL != jobinfo->submit->login_shell) {
        len += strlen(jobinfo->submit->login_shell) + 1;
        len += sizeof(int);
    }
    if (NULL != jobinfo->submit->execute_host_type) {
        len += strlen(jobinfo->submit->execute_host_type) + 1;
        len += sizeof(int);
    }
    if (NULL != jobinfo->submit->user_group) {
        len += strlen(jobinfo->submit->user_group) + 1;
        len += sizeof(int);
    }

    if (NULL != jobinfo->job_GPU) {

        unsigned int n;
        len += sizeof(struct jobInfoGPU);
        len += jobinfo->num_execute_node * sizeof(struct jobHostGPUinfo);

        for (i=0; i<jobinfo->num_execute_node; i++) {

            len += jobinfo->job_GPU->alloc_job_gpu[i].num_gpu * sizeof(struct gpuInfo);
            for (n = 0; n < jobinfo->job_GPU->alloc_job_gpu[i].num_gpu; n++) {
                len += strlen(jobinfo->job_GPU->alloc_job_gpu[i].gpus[n].model);
                len += sizeof(int);
            }

            len += sizeof(struct jobResourceUsage);
            len += jobinfo->resource_usage[i].npgids * sizeof(int);
            len += jobinfo->resource_usage[i].npids * (sizeof(int) + sizeof(struct pidInfo));
        }        
    }

    if (NULL != jobinfo->job_numa && NULL != jobinfo->job_numa->alloc_job_numa) {

        len += sizeof(struct jobInfoNuma);
        len += jobinfo->num_execute_node * sizeof(struct jobHostUsedcore);

        for (i=0; i<jobinfo->num_execute_node; i++) {

            int numUsedCore = LIST_NUM_ENTS(jobinfo->job_numa->alloc_job_numa[i].used_numa);
	    len += numUsedCore * sizeof(struct usedCoreInfoDown);
        }        
    }

    return len;
} /* end function sizeof_quickpool_jobinfo */

/**
 * @brief       XDR: xdr function to exchange job information header.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   jobinfo         #2: single job data to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data, number of load index
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 *              This is for exchanging QuickPoolJobInfo between command and JS.
 */
bool_t
libxdr_jobinfo(XDR *xdrs, void *jobinfo, struct header *hdr, void *argument)
{
    struct QuickPoolJobInfo *info = (struct QuickPoolJobInfo *)jobinfo;
    unsigned int *numIndicies = (unsigned int *)argument;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (JGRP_NODE_GROUP == info->job_type) {
            gf_xdr_free(xdr_jobinfo_array, info);
            return (TRUE);
        }

        FREEUP(info->load_schedule);
        FREEUP(info->load_stop);
        FREEUP(info->pending_reasons);
        for (i=0; i<info->num_execute_node; i++) {
            FREEUP(info->execute_nodes[i]);
            if (NULL != info->resource_usage) {
                gf_xdr_free(xdr_job_usage, &(info->resource_usage[i]));
            }
        }
        FREEUP(info->execute_nodes);
        FREEUP(info->resource_usage);
        FREEUP(info->num_slot);

        FREEUP(info->execute_homedir);
        FREEUP(info->execute_cwd);
        FREEUP(info->execute_user);

        gf_xdr_free(libxdr_jobinfo_submit, info->submit);
        FREEUP(info->submit);

        free_job_usednuma(info->num_execute_node, info->job_numa);
        free_job_usedgpu(info->num_execute_node, info->job_GPU);

        return (TRUE);
    }

    if (!xdr_int(xdrs, &(info->job_type))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(job_type)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    for (i = 0; i < NUM_JGRP_COUNTERS; i++ ) {

        if (!xdr_int(xdrs, &(info->counter[i]))) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_int(counter)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (JGRP_NODE_GROUP == info->job_type) {
        return(xdr_jobinfo_array(xdrs, info, hdr, NULL));
    }

    if (!xdr_jobID(xdrs, &(info->jobid), hdr, argument)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_jobID");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(xdr_int(xdrs, &(info->status)) && xdr_int(xdrs, &(info->reason_id))
          && xdr_int(xdrs, &(info->reason_detail))
          && xdr_long(xdrs, &(info->start_time))
          && xdr_long(xdrs, &(info->end_time))
          && xdr_float(xdrs, &(info->used_cpu_time))
          && xdr_u_int(xdrs, &(info->num_execute_node))
          && xdr_u_int(xdrs, numIndicies)
          && xdr_u_int(xdrs, &info->num_pending_reason)
          && xdr_long(xdrs, &(info->max_mem))
          && xdr_long(xdrs, &(info->max_swap)))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(status and so on)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < *numIndicies) {

        info->load_schedule = (float *)calloc(*numIndicies, sizeof(float));
        info->load_stop = (float *)calloc(*numIndicies, sizeof(float));
        if (NULL == info->load_schedule || NULL == info->load_stop) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", *numIndicies*sizeof(float)*2);
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<*numIndicies; i++) {

        if (!(xdr_float(xdrs, &info->load_schedule[i])
              && xdr_float(xdrs, &info->load_stop[i]))) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_float(load_stop)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (XDR_DECODE == xdrs->x_op && 0 < info->num_pending_reason) {

        info->pending_reasons = (int *)calloc(info->num_pending_reason, sizeof(int));
        if (NULL == info->pending_reasons) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", info->num_pending_reason*sizeof(int));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<info->num_pending_reason; i++) {

        if (!xdr_int(xdrs, &info->pending_reasons[i])) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_int(pending_reasons)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (XDR_DECODE == xdrs->x_op && 0 < info->num_execute_node) {

        info->execute_nodes = (char **)calloc(info->num_execute_node, sizeof(char *));
        if (NULL == info->execute_nodes) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", info->num_execute_node*sizeof(char *));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }

        info->num_slot = (unsigned int *)calloc(info->num_execute_node, sizeof(int));
        if (NULL == info->num_slot) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", info->num_execute_node*sizeof(int));
            FREEUP(info->execute_nodes);
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }

        info->resource_usage = (struct jobResourceUsage *)calloc(info->num_execute_node,
                                                                 sizeof(struct jobResourceUsage));
        if (NULL == info->resource_usage) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", info->num_execute_node*sizeof(struct jobResourceUsage));
            FREEUP(info->execute_nodes);
            FREEUP(info->num_slot);
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<info->num_execute_node; i++ ) {

        if (!gf_xdr_string(xdrs, &(info->execute_nodes[i]), hdr, NULL)) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_string(execute_nodes)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }

        if (!xdr_u_int(xdrs, &(info->num_slot[i]))) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_u_int(num_slot)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }

        if (!(xdr_job_usage(xdrs, &(info->resource_usage[i]), hdr, NULL))) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_job_usage", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (XDR_DECODE == xdrs->x_op) {

        info->submit = (struct submitRequest*)calloc(1, sizeof(struct submitRequest));
        if (NULL == info->submit) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", sizeof(struct submitRequest));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    if (!gf_xdr_element(xdrs, info->submit, hdr, libxdr_jobinfo_submit, NULL)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "libxdr_jobinfo_submit");
        return FALSE;
    }

    if (!(xdr_int(xdrs, &info->exit_stat)
          && gf_xdr_string(xdrs, &info->execute_homedir, hdr, NULL)
          && gf_xdr_string(xdrs, &info->execute_cwd, hdr, NULL)
          && gf_xdr_string(xdrs, &info->execute_user, hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(exit_stat and so on)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(xdr_long(xdrs, &info->reserving_time)
          && xdr_long(xdrs, &(info->usage_update_time))
          && xdr_long(xdrs, &(info->possible_start)))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_long(reserving_time and so on)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!xdr_u_short(xdrs, &info->port)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_short(port)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!xdr_int(xdrs, &info->job_priority)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(job_priority)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    int GPUflag = FALSE;
    if (XDR_ENCODE == xdrs->x_op && NULL != info->job_GPU) {
        GPUflag = TRUE;
    }

    if (!xdr_int(xdrs, &GPUflag)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(gpu flag)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }      

    if (GPUflag) {

        if (XDR_DECODE == xdrs->x_op) {

            info->job_GPU = (struct jobInfoGPU *)calloc(1, sizeof(struct jobInfoGPU));
            if (NULL == info->job_GPU) {
                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                            "calloc", sizeof(struct jobInfoGPU));
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }
        }

        struct jobInfoGPU *jobGPU = info->job_GPU;
        if (!xdr_int(xdrs, &jobGPU->exclusive)) {
            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(gpu exclusive)");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        } 

        if (XDR_DECODE == xdrs->x_op) {

            jobGPU->alloc_job_gpu = (struct jobHostGPUinfo *)calloc(info->num_execute_node,
                                                                    sizeof(struct jobHostGPUinfo));
            if (NULL == jobGPU->alloc_job_gpu) {
                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                            "calloc", info->num_execute_node*sizeof(struct jobHostGPUinfo));
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }        
        }
    
        for (i=0; i<info->num_execute_node; i++) {

            if (!xdr_u_int(xdrs, &jobGPU->alloc_job_gpu[i].num_gpu)) {
                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_u_int(num_gpu)", i);
                quickpool_errno = ERROR_XDR;
                return FALSE;
            } 

            unsigned int num;
            num = jobGPU->alloc_job_gpu[i].num_gpu;
            if (XDR_DECODE == xdrs->x_op) {

                jobGPU->alloc_job_gpu[i].gpus = (struct gpuInfo *)calloc(num,
                                                                         sizeof(struct gpuInfo));
                if (NULL == jobGPU->alloc_job_gpu[i].gpus) {
                    log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                                "calloc", num*sizeof(struct gpuInfo));
                    quickpool_errno = ERROR_MEMORY;
                    return FALSE;
                }
            }

            unsigned int j;
            for (j=0; j<num; j++) {

                if (!(xdr_double(xdrs, &jobGPU->alloc_job_gpu[i].gpus[j].alloc_mem)
                      && xdr_int(xdrs, &jobGPU->alloc_job_gpu[i].gpus[j].index)
                      && xdr_float(xdrs, &jobGPU->alloc_job_gpu[i].gpus[j].factor)
                      && gf_xdr_string(xdrs, &jobGPU->alloc_job_gpu[i].gpus[j].model, hdr, NULL))) {

                    log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_double(gpus)", j);
                    quickpool_errno = ERROR_XDR;
                    return FALSE;
                }                
            }
        }
    }
    
    unsigned int numaFlag=0;
    if (XDR_ENCODE == xdrs->x_op && NULL != info->job_numa && NULL != info->job_numa->alloc_job_numa) {
        numaFlag = info->num_execute_node;
    }

    if (!xdr_u_int(xdrs, &numaFlag)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(numa flag)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }    

    if (0 < numaFlag) {

        if (XDR_DECODE == xdrs->x_op) {

            info->job_numa = (struct jobInfoNuma *)calloc(1, sizeof(struct jobInfoNuma));
            if (NULL == info->job_numa) {
                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                            "calloc", sizeof(struct jobInfoNuma));
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }
        }

        struct jobInfoNuma *jobNuma = info->job_numa;
        if (XDR_DECODE == xdrs->x_op) {

            jobNuma->alloc_job_numa = (struct jobHostUsedcore *)calloc(numaFlag,
                                                                       sizeof(struct jobHostUsedcore));
            if (NULL == jobNuma->alloc_job_numa) {
                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                            "calloc", numaFlag*sizeof(struct jobHostUsedcore));
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }        
        }

        if (NULL != info->job_numa) {
            if (!(xdr_int(xdrs, &jobNuma->bind_type)
                  && xdr_int(xdrs, &jobNuma->same)
                  && xdr_int(xdrs, &jobNuma->exclusive)
                  && xdr_int(xdrs, &jobNuma->num_bind)
                  && xdr_int(xdrs, &jobNuma->cpu_bind_type)
                  && xdr_int(xdrs, &jobNuma->mem_bind_type))) {

                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(job numa)");
                quickpool_errno = ERROR_XDR;
                return FALSE;
            }           

            for (i=0; i<numaFlag; i++) {

                int numCores = LIST_NUM_ENTS(jobNuma->alloc_job_numa[i].used_numa);
                if (!xdr_int(xdrs, &numCores)) {
                    log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_int(numCores)", i);
                    quickpool_errno = ERROR_XDR;
                    return FALSE;
                }

                struct usedCoreInfoDown *tmpCores;
                if (XDR_ENCODE == xdrs->x_op) {

                    for (tmpCores = (struct usedCoreInfoDown *)jobNuma->alloc_job_numa[i].used_numa->back; 
                         tmpCores != (struct usedCoreInfoDown *)jobNuma->alloc_job_numa[i].used_numa;
                         tmpCores = (struct usedCoreInfoDown *)tmpCores->back) {

                        if (!(xdr_int(xdrs, &tmpCores->parent_index)
                              && xdr_int(xdrs, &tmpCores->pparent_index)
                              && xdr_int(xdrs, &tmpCores->index)
                              && xdr_int(xdrs, &tmpCores->index_sibling))) {

                            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_int(index)", i);
                            quickpool_errno = ERROR_XDR;
                            return FALSE;
                        }
                    }
                } else if (XDR_DECODE == xdrs->x_op) {

                    jobNuma->alloc_job_numa[i].used_numa = gf_list_make("job used numa list on node");

                    int j;
                    for (j=0; j<numCores; j++) {

                        tmpCores = (struct usedCoreInfoDown *)calloc(1, sizeof(struct usedCoreInfoDown));
                        if (!(xdr_int(xdrs, &tmpCores->parent_index)
                              && xdr_int(xdrs, &tmpCores->pparent_index)
                              && xdr_int(xdrs, &tmpCores->index)
                              && xdr_int(xdrs, &tmpCores->index_sibling))) {

                            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_int(index)", i);
                            quickpool_errno = ERROR_XDR;
                            return FALSE;
                        }

                        gf_list_insert(jobNuma->alloc_job_numa[i].used_numa,
                                       jobNuma->alloc_job_numa[i].used_numa->back, (LIST_T *)tmpCores);
                    }
                }
            }
        } 
    } // end if (0 < coresFlag)

    return TRUE;
} // end function libxdr_jobinfo

/**
 * @brief       Calculate size of job group reply.
 *
 * @param[in]   reply         #1: job group reply
 *
 * @retval      >0            #1: size of job group reply
 */
unsigned int
sizeof_jobgroup_reply(struct QuickPoolJobGroupReply *reply)
{
    unsigned int len, i;

    len = sizeof(struct QuickPoolJobGroupReply);

    len += sizeof(int);
    for (i = 0; i < reply->num_jobgroup; i++) {
        len += sizeof(struct QuickPoolJobGroup);
        len += strlen(reply->job_groups[i].path) + 1;
        len += sizeof(int);
        len += strlen(reply->job_groups[i].name) + 1;
        len += sizeof(int);
    }

    return len;
} // end function sizeof_jobgroup_reply

/**
 * @brief       XDR: xdr function to exchange job group information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   groupreply      #2: number of job groups and their information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_jobgroup_reply(XDR *xdrs, void *groupreply, struct header *hdr, void *argument)
{
    struct QuickPoolJobGroupReply *reply = (struct QuickPoolJobGroupReply *)groupreply;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        for (i=0; i<reply->num_jobgroup; i++) {
            gf_xdr_free(xdr_jobgroup, &(reply->job_groups[i]));
        }
        FREEUP(reply->job_groups);

        return TRUE;
    }

    if (!xdr_u_int(xdrs, &(reply->num_jobgroup))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_jobgroup)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_jobgroup) {

        reply->job_groups = (struct QuickPoolJobGroup *)calloc(reply->num_jobgroup,
                                                               sizeof(struct QuickPoolJobGroup));
        if (NULL == reply->job_groups) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        reply->num_jobgroup*sizeof(struct QuickPoolJobGroup));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<reply->num_jobgroup; i++) {

        if (!gf_xdr_element(xdrs, &(reply->job_groups[i]), hdr, xdr_jobgroup, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(job_groups)", i);
            if (XDR_DECODE == xdrs->x_op) {
                reply->num_jobgroup = i;
            }

            return FALSE;
        }
    }

    return TRUE;
} // end function libxdr_jobgroup_reply

/**
 * @brief       XDR: xdr function to exchange job message.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   jobmsgreply     #2: number of job message and
 *                                      job messages to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_jobmsg_reply(XDR *xdrs, void *jobmsgreply, struct header *hdr, void *argument)
{
    struct QuickPoolJobMsgReply *reply = (struct QuickPoolJobMsgReply *)jobmsgreply;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        for (i=0; i<reply->num_message; i++) {
            gf_xdr_free(xdr_jobmsg, &(reply->messages[i]));
        }
        FREEUP(reply->messages);

        return TRUE;
    }

    if (!xdr_u_int(xdrs, &(reply->num_message))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_message)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_message) {

        reply->messages = (struct QuickPoolJobMsg *)calloc(reply->num_message,
                                                           sizeof(struct QuickPoolJobMsg));
        if (NULL == reply->messages) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        reply->num_message*sizeof(struct QuickPoolJobMsg));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<reply->num_message; i++) {

        if (!gf_xdr_element(xdrs, &(reply->messages[i]), hdr, xdr_jobmsg, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(message)", i);
            if (XDR_DECODE == xdrs->x_op) {
                reply->num_message = i;
            }
            return FALSE;
        }
    }

    return TRUE;
} // end function libxdr_jobmsg_reply

/**
 * @brief       XDR: xdr function to exchange job dependency.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   jobdepreply     #2: number of job dependency and
 *                                      their information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_jobdep_reply(XDR *xdrs, void *jobdepreply, struct header *hdr, void *argument)
{
    struct QuickPoolJobDepReply *reply = (struct QuickPoolJobDepReply *)jobdepreply;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        for (i=0; i<reply->num_dependency; i++) {
            gf_xdr_free(xdr_jobdep, &(reply->dependencies[i]));
        }
        FREEUP(reply->dependencies);

        return TRUE;
    }

    if (!xdr_u_int(xdrs, &(reply->num_dependency))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_dependency)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_dependency) {

        reply->dependencies = (struct QuickPoolJobDep *)calloc(reply->num_dependency,
                                                               sizeof(struct QuickPoolJobDep));
        if (NULL == reply->dependencies) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        reply->num_dependency*sizeof(struct QuickPoolJobDep));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i = 0; i < reply->num_dependency; i++) {

        if (!gf_xdr_element(xdrs, &(reply->dependencies[i]), hdr, xdr_jobdep, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(dependency)", i);
            if (XDR_DECODE == xdrs->x_op) {
                reply->num_dependency = i;
            }
            return FALSE;
        }
    }

    return TRUE;
} // end function libxdr_jobdep_reply

bool_t
libxdr_peek_reply(XDR *xdrs, void *peekreply, struct header *hdr, void *argument)
{
    struct QuickPoolPeekReply *reply = (struct QuickPoolPeekReply *)peekreply;

    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        FREEUP(reply->output_file);
        return TRUE;
    }

    if (!gf_xdr_string(xdrs, &(reply->output_file), hdr, NULL)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(output_file)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    return TRUE;
} // end function libxdr_peek_reply

/**
 * @brief       XDR: xdr function to exchange file.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   rcpreply        #2: number of files and their content to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_filecopy(XDR *xdrs, void *rcpreply, struct header *hdr, void *argument)
{
    struct QuickPoolFileCopyReply *reply = (struct QuickPoolFileCopyReply *)rcpreply;

    int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == reply) {
            return TRUE;
        }

        for (i=0; i<reply->num_buf; i++) {
            FREEUP(reply->file_buffer[i]);
        }

        FREEUP(reply);

        return TRUE;
    }

    if (!(xdr_int(xdrs, &reply->num_buf))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_buf)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < reply->num_buf) {

        reply->file_buffer = (char **)calloc(reply->num_buf, sizeof(char *));
        if (NULL == reply->file_buffer) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        reply->num_buf*sizeof(char *));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i = 0; i < reply->num_buf; i++) {

        if (!gf_xdr_string(xdrs, &(reply->file_buffer[i]), hdr, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_string(file_buffer)", i);
            if (XDR_DECODE == xdrs->x_op) {
                reply->num_buf = i;
            }

            return FALSE;
        }
    }

    return TRUE;
} // end function libxdr_filecopy

/**
 * @brief       XDR: xdr function to exchange job pid info.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   pidinfo         #2: job pid info to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
xdr_pid_info(XDR *xdrs, void *pidinfo, struct header *hdr, void *argument)
{
    struct pidInfo *info = (struct pidInfo *)pidinfo;

    if (!xdr_int(xdrs, &info->pid)) {
        return FALSE;
    }

    if (!xdr_int(xdrs, &info->ppid)) {
        return FALSE;
    }

    if (!xdr_int(xdrs, &info->pgid)) {
        return FALSE;
    }

    return TRUE;
} // end function xdr_pid_info

/**
 * @brief       XDR: xdr function to exchange job pgid info.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   pgidinfo         #2: job pgid info to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
xdr_pgid(XDR *xdrs, void *pgidinfo, struct header *hdr, void *argument)
{
    int *pgid = (int *)pgidinfo;

    if (!xdr_int(xdrs, pgid)) {
        return FALSE;
    }

    return TRUE;
} // end function xdr_pgid

/**
 * @brief       XDR: xdr function to exchange job resource usage.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   usage           #2: job resource usage to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
xdr_job_usage(XDR *xdrs, void *usage, struct header *hdr, void *argument)
{
    struct jobResourceUsage *runRusage = (struct jobResourceUsage *)usage;

    if (XDR_FREE == xdrs->x_op) {

        if (NULL == runRusage) {
            return TRUE;
        }

        FREEUP(runRusage->pidinfo);
        FREEUP(runRusage->pgid);
        runRusage->npids = 0;
        runRusage->npgids = 0;

        return TRUE;
    }

    if (!(xdr_long(xdrs, &runRusage->mem) && xdr_long(xdrs, &runRusage->swap)
          && xdr_long(xdrs, &runRusage->utime) && xdr_long(xdrs, &runRusage->stime))) {
        return FALSE;
    }

    if (!(xdr_u_int(xdrs, &runRusage->npids))) {
        return FALSE;
    }

    if (xdrs->x_op == XDR_DECODE && runRusage->npids > 0) {
        runRusage->pidinfo = (struct pidInfo *)calloc(runRusage->npids, sizeof(struct pidInfo));
        if (NULL == runRusage->pidinfo) {
            quickpool_errno = ERROR_MEMORY;
            runRusage->npids = 0;
            return FALSE;
        }
    }

    unsigned int i;
    for (i = 0; i < runRusage->npids; i++) {
        if (!gf_xdr_element(xdrs, (void *) &(runRusage->pidinfo[i]), hdr, xdr_pid_info, NULL)) {
            if (xdrs->x_op == XDR_DECODE) {
                FREEUP(runRusage->pidinfo);
                runRusage->npids = 0;
            }
            return FALSE;
        }
    }

    if (!(xdr_u_int(xdrs, &runRusage->npgids))) {
        return FALSE;
    }

    if (xdrs->x_op == XDR_DECODE && runRusage->npgids > 0) {
        runRusage->pgid = (int *)calloc(runRusage->npgids, sizeof(int));
        if (runRusage->pgid == NULL) {
            quickpool_errno = ERROR_MEMORY;
            runRusage->npgids = 0;
            return FALSE;
        }
    }

    for (i = 0; i < runRusage->npgids; i++) {
        if (!gf_xdr_element(xdrs, (void *)&(runRusage->pgid[i]), hdr, xdr_pgid, NULL)) {
            if (xdrs->x_op == XDR_DECODE) {
                FREEUP(runRusage->pgid);
                runRusage->npgids = 0;
                runRusage->pgid = NULL;
            }
            return FALSE;
        }
    }

    return TRUE;
} // end function xdr_job_usage

/**
 * @brief       XDR: xdr function to exchange job id.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   job             #2: job id to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
xdr_jobID(XDR *xdrs, void *job, struct header *hdr, void *argument)
{
    int jobBaseId;
    int jobIndex;

    JOBID_T *jobID = (JOBID_T *)job;

    if (xdrs->x_op == XDR_ENCODE) {
        split_jobid(*jobID, &jobBaseId, &jobIndex);
    }

    if (!(xdr_int(xdrs, &jobBaseId) && xdr_int(xdrs, &jobIndex))) {
        return FALSE;
    }

    if (xdrs->x_op == XDR_DECODE) {
        combine_jobid(jobID, jobBaseId, jobIndex);
    }

    return TRUE;
} // end function xdr_jobID

/**
 * @brief       XDR: xdr function to exchange file data.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   filedata        #2: file data to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
xdr_file_data(XDR *xdrs, void *filedata, struct header *hdr, void *argument)
{
    struct lenData *ld = (struct lenData *)filedata;
    char *sp;

    if (xdrs->x_op == XDR_FREE) {
        if (0 < ld->len) {
            FREEUP(ld->data);
        }
        return TRUE;
    }

    if (!xdr_u_int(xdrs, &ld->len))
        return FALSE;

    if (ld->len == 0) {
        ld->data = NULL;
        return TRUE;
    }

    if (xdrs->x_op == XDR_DECODE && 0 < ld->len) {
        if ((ld->data = (char *)calloc(ld->len, sizeof(char))) == NULL) {
            return FALSE;
        }
    }

    sp = ld->data;
    if (!xdr_bytes(xdrs, &sp, (u_int *) &ld->len, ld->len)) {
        if (xdrs->x_op == XDR_DECODE) {
            FREEUP(ld->data);
        }
        return FALSE;
    }

    return TRUE;
} // end function xdr_file_data

bool_t
xdr_execution_file(XDR *xdrs, void *xfile, struct header *hdr, void *argument)
{
    char *sp;
    struct execution_file *xf = (struct execution_file *)xfile;

    if (xdrs->x_op == XDR_DECODE) {
        xf->in_file[0] = '\0';
        xf->out_file[0] = '\0';
    }
    sp = xf->in_file;

    if (!xdr_string(xdrs, &sp, PATH_MAX)) {
        return FALSE;
    }

    sp = xf->out_file;
    if (!xdr_string(xdrs, &sp, PATH_MAX)) {
        return FALSE;
    }

    if (!xdr_u_int(xdrs, &xf->direction)) {
        return FALSE;
    }

    return TRUE;
}

/**
 * @brief       XDR: xdr function to exchange job submission request between JM and JS.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   submit          #2: job submission request to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_jobinfo_submit(XDR *xdrs, void *submit, struct header *hdr, void *argument)
{
    unsigned int i;
    unsigned int nLimits;
    struct submitRequest *submitReq = (struct submitRequest *)submit;

    if (xdrs->x_op == XDR_FREE) {
        FREEUP(submitReq->job_name);
        FREEUP(submitReq->user);
        FREEUP(submitReq->queue);

        free_string_array(submitReq->spec_nodes, submitReq->num_spec_node);
        submitReq->spec_nodes = NULL;

        FREEUP(submitReq->resource_requirement);
        FREEUP(submitReq->dependency);
        FREEUP(submitReq->home_dir);
        FREEUP(submitReq->input_file);
        FREEUP(submitReq->output_file);
        FREEUP(submitReq->error_file);
        FREEUP(submitReq->command);
        FREEUP(submitReq->new_command);
        FREEUP(submitReq->exec_files);
        FREEUP(submitReq->script);
        FREEUP(submitReq->from_node);
        FREEUP(submitReq->cwd);
        FREEUP(submitReq->prejob_command);
        FREEUP(submitReq->postjob_command);
        FREEUP(submitReq->mail_user);
        FREEUP(submitReq->project);
        FREEUP(submitReq->login_shell);
        FREEUP(submitReq->execute_host_type);
        FREEUP(submitReq->user_group);
        FREEUP(submitReq->job_group);
        FREEUP(submitReq->chkpnt_dir);
        FREEUP(submitReq->chkpnt_method);
        FREEUP(submitReq->gpu_model);
        FREEUP(submitReq->gpu_mps);
        FREEUP(submitReq->requeue_exitcode);

        return (TRUE);
    }

    if (!(xdr_u_int(xdrs, (unsigned int *)&submitReq->options)
          && gf_xdr_string(xdrs, &submitReq->queue, hdr, NULL)
          && gf_xdr_string(xdrs, &submitReq->resource_requirement, hdr, NULL)
          && xdr_u_int(xdrs, &submitReq->num_job_slot)
          && xdr_u_int(xdrs, &submitReq->max_job_slot))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(options, queue, resreq, num_job_slot)");
        return FALSE;
    }

    if (!(gf_xdr_string(xdrs, &submitReq->from_node, hdr, NULL)
          && gf_xdr_string(xdrs, &submitReq->dependency, hdr, NULL)
          && gf_xdr_string(xdrs, &submitReq->job_name, hdr, NULL)
          && gf_xdr_string(xdrs, &submitReq->command, hdr, NULL)
          && gf_xdr_string(xdrs, &submitReq->script, hdr, NULL)
          && gf_xdr_string(xdrs, &submitReq->input_file, hdr, NULL)
          && gf_xdr_string(xdrs, &submitReq->output_file, hdr, NULL)
          && gf_xdr_string(xdrs, &submitReq->error_file, hdr, NULL)
          && gf_xdr_string(xdrs, &submitReq->prejob_command, hdr, NULL)
          && gf_xdr_string(xdrs, &submitReq->postjob_command, hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(from_node and so on)");
        return FALSE;
    }

    if (!xdr_u_int(xdrs, &submitReq->num_spec_node)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_spec_node)");
        return FALSE;
    }

    if (xdrs->x_op == XDR_DECODE && 0 < submitReq->num_spec_node) {
        submitReq->spec_nodes = (char **)calloc(submitReq->num_spec_node, sizeof(char *));
        if (NULL == submitReq->spec_nodes) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", submitReq->num_spec_node*sizeof(char *));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i = 0; i < submitReq->num_spec_node;i++ ) {
        if (!gf_xdr_string(xdrs, &submitReq->spec_nodes[i], hdr, NULL)) {

            submitReq->num_spec_node = i;
            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(spec_nodes)");

            return FALSE;
        }
    }

    nLimits = RESOURCE_LIMIT_NUM;
    if (!xdr_u_int(xdrs, &nLimits)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(nLimits)");
        return FALSE;
    }

    for (i = 0; i < nLimits; i++) {

        if (!xdr_int(xdrs, &submitReq->job_ulimit[i])) {
            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(job_ulimit)");
            return FALSE;
        }
    }

    if (!(xdr_long(xdrs, (long *)&submitReq->submit_time)
          && xdr_long(xdrs, (long *)&submitReq->begin_time)
          && xdr_long(xdrs, (long *)&submitReq->terminate_time)
          && xdr_int(xdrs,&submitReq->umask) && xdr_int(xdrs,&submitReq->window_signal)
          && xdr_int(xdrs,&submitReq->execute_jobpid)
          && gf_xdr_string(xdrs, &submitReq->home_dir, hdr, NULL)
          && gf_xdr_string(xdrs, &submitReq->cwd, hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(submit_time and so on)");
        return FALSE;
    }

    if (!xdr_u_int(xdrs, &submitReq->num_exec_files)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_exec_files)");
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < submitReq->num_exec_files) {

        if ((submitReq->exec_files = (struct execution_file *)
             calloc(submitReq->num_exec_files, sizeof(struct execution_file))) == NULL) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", submitReq->num_exec_files*sizeof(struct execution_file));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i = 0; i < submitReq->num_exec_files; i++) {

        if (!gf_xdr_element(xdrs, &(submitReq->exec_files[i]), hdr, xdr_execution_file, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(exec_files)", i);
            quickpool_errno = ERROR_XDR;
            if (XDR_DECODE == xdrs->x_op) {
                submitReq->num_exec_files = 0;
            }

            return FALSE;
        }
    }

    if (!gf_xdr_string(xdrs, &submitReq->mail_user, hdr, NULL)) {
        return FALSE;
    }

    if (!gf_xdr_string(xdrs, &submitReq->project, hdr, NULL)) {
        return FALSE;
    }

    if (!gf_xdr_string(xdrs, &submitReq->login_shell, hdr, NULL)) {
        return FALSE;
    }

    if (!gf_xdr_string(xdrs, &submitReq->execute_host_type, hdr, NULL)) {
        return FALSE;
    }

    if (!xdr_int(xdrs, &submitReq->options2)) {
        return FALSE;
    }

    if (!xdr_int(xdrs, &submitReq->spec_priority)) {
        return FALSE;
    }

    if (!gf_xdr_string(xdrs, &submitReq->user_group, hdr, NULL)) {
        return FALSE;
    }

    if (!gf_xdr_string(xdrs, &submitReq->job_group, hdr, NULL)) {
        return FALSE;
    }

    if (!(xdr_int(xdrs, (int *)(&submitReq->uid))
          && gf_xdr_string(xdrs, &submitReq->user, hdr, NULL))) {
        return FALSE;
    }

    if (!(xdr_u_int(xdrs, &submitReq->num_gpu) 
          && gf_xdr_string(xdrs, &submitReq->gpu_model, hdr, NULL)
          && xdr_int(xdrs, &submitReq->gpu_exclusive)
          && xdr_double(xdrs, &submitReq->gpu_mem)
          && gf_xdr_string(xdrs, &submitReq->gpu_mps, hdr, NULL))) {

        return FALSE;
    }

    if (!(gf_xdr_string(xdrs, &submitReq->chkpnt_dir, hdr, NULL)
          && gf_xdr_string(xdrs, &submitReq->chkpnt_method, hdr, NULL)
          && xdr_u_int(xdrs, &submitReq->chkpnt_duration))) {
        return FALSE;
    }    

    if (!gf_xdr_string(xdrs, &submitReq->requeue_exitcode, hdr, NULL)) {
        return FALSE;
    }

    if (!xdr_u_int(xdrs, &submitReq->thread_pertask)) {
        return FALSE;
    }

    return TRUE;
} // end function libxdr_jobinfo_submit

/**
 * @brief       XDR: xdr function to exchange job basic information between JM and JS.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   jobbase         #2: job basic information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
libxdr_jobbase(XDR *xdrs, void *jobbase, struct header *hdr, void *argument)
{
    unsigned int i;
    struct jobInfo *base = (struct jobInfo *)jobbase;

    if (XDR_FREE == xdrs->x_op) {

        if (NULL == base) {
            return TRUE;
        }

        for(i=0; i<base->number_node; i++) {
            FREEUP(base->node_execinfo[i].host_name);
            gf_list_free(base->node_execinfo[i].alloc_cores, NULL);
            gf_list_free(base->node_execinfo[i].alloc_gpus, NULL);
        }
        FREEUP(base->node_execinfo);

        for(i=0; i<base->num_environment; i++) {
            FREEUP(base->environment[i]);
        }
        FREEUP(base->environment);

        FREEUP(base->prequeue_command);
        FREEUP(base->postqueue_command);
        FREEUP(base->exec_files);
        FREEUP(base->schedule_host);
        FREEUP(base->execute_user);
        FREEUP(base->execute_cwd);
        FREEUP(base->execute_home);
        FREEUP(base->run_window);
        FREEUP(base->requeue_exitcode);
        FREEUP(base->resume_condition);
        FREEUP(base->stop_condition);
        FREEUP(base->suspend_command);
        FREEUP(base->resume_command);
        FREEUP(base->terminate_command);
        FREEUP(base->prepost_user);

        gf_xdr_free(libxdr_thresholds, &(base->thresholds));
        gf_xdr_free(xdr_file_data, &(base->eexec));
        gf_xdr_free(xdr_file_data, &(base->job_file));
        gf_xdr_free(libxdr_jobinfo_submit, base->submit);
        FREEUP(base->submit);

        return TRUE;
    }

    if (!xdr_jobID(xdrs, (void *)&(base->jobid), hdr, argument)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_jobID");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op) {

        base->submit = (struct submitRequest *)calloc(1, sizeof(struct submitRequest));
        if (NULL == base->submit) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        sizeof(struct submitRequest));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    if (!gf_xdr_element(xdrs, base->submit, hdr, libxdr_jobinfo_submit, NULL)) {
        return FALSE;
    }

    char strJobId[32];
    unsigned int nLimits = RESOURCE_LIMIT_NUM;
    if (!xdr_u_int(xdrs, &nLimits)) {

        log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                    jobid_2string(base->jobid, strJobId), "xdr_int", "nLimits");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    for (i=0; i<nLimits && i<RESOURCE_LIMIT_NUM; i++) {

        if(!xdr_resource_limit(xdrs, (void *)&base->resource_limits[i], hdr, NULL)) {

            log_message(ERR, NOCLASS, STR_JOB_FAIL_S, __func__,
                        jobid_2string(base->jobid, strJobId), "xdr_resource_limit");
            return FALSE;
        }
    }

    if (RESOURCE_LIMIT_NUM < nLimits) {

        for (i=RESOURCE_LIMIT_NUM; i<nLimits; i++) {

            struct resourceLimit resLimit;
            if (!xdr_resource_limit(xdrs, (void *)&resLimit, hdr, NULL)) {

                log_message(ERR, NOCLASS, STR_JOB_FAIL_S, __func__,
                            jobid_2string(base->jobid, strJobId), "xdr_resource_limit");
                return FALSE;
            }
        }
    }

    if (!(xdr_short(xdrs, &base->nice) && xdr_int(xdrs, &base->chkpnt_signal)
          && xdr_int(xdrs, &base->act_pid) && xdr_int(xdrs, &base->mig)
          && xdr_long(xdrs, &base->suspend_time) && xdr_float(xdrs, &base->lastCpuTime))) {

        log_message(ERR, NOCLASS, STR_FUNC_S_FAIL, __func__, "xdr_int", "nice and so on");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(xdr_int(xdrs, &base->status) && xdr_int(xdrs, &base->reasons)
          && xdr_int(xdrs, &base->subreasons) && xdr_long(xdrs, &base->start_time)
          && xdr_u_int(xdrs, &base->running) && xdr_int(xdrs, &base->job_pid)
          && xdr_int(xdrs, &base->job_pgid) && xdr_int(xdrs, &base->restart_pid)
          && xdr_int(xdrs, &base->signal) && xdr_int(xdrs, &base->job_attribute))) {

        log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                    jobid_2string(base->jobid, strJobId), "xdr_int", "status and so on");
        quickpool_errno = ERROR_XDR;
	return FALSE;
    }

    if (!xdr_u_int(xdrs, &base->number_node)) {

        log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                    jobid_2string(base->jobid, strJobId), "xdr_u_int", "number_node");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < base->number_node) {

        base->node_execinfo = (struct nodeExecution *)calloc(base->number_node,
                                                             sizeof(struct nodeExecution));
        if (NULL == base->node_execinfo) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc", base->number_node);
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<base->number_node; i++) {

        struct nodeExecution *execInfo = &(base->node_execinfo[i]);
        if (!gf_xdr_string(xdrs, &(execInfo->host_name), hdr, NULL)) {
            log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                        jobid_2string(base->jobid, strJobId), "gf_xdr_string", "host_name");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }

        unsigned int numCore = LIST_NUM_ENTS(execInfo->alloc_cores);
        unsigned int numGpu = LIST_NUM_ENTS(execInfo->alloc_gpus);
        if (!(xdr_u_int(xdrs, &(execInfo->num_slot)) && xdr_u_int(xdrs, &numCore)
              && xdr_u_int(xdrs, &numGpu))) {

            log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                        jobid_2string(base->jobid, strJobId), "xdr_u_int", "num_slot");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }

        if (XDR_DECODE == xdrs->x_op && 0 < numCore) {

            execInfo->alloc_cores = gf_list_make("job allocate numa cores list");
            if (NULL == execInfo->alloc_cores) {
                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc", numCore);
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }
        }

        if (XDR_ENCODE == xdrs->x_op && 0 < numCore) {
            struct usedCoreInfoDown *core;
            for (core = (struct usedCoreInfoDown *)execInfo->alloc_cores->back; 
                 core != (struct usedCoreInfoDown *)execInfo->alloc_cores;
                 core = (struct usedCoreInfoDown *)core->back) {

                if (!xdr_int(xdrs, &(core->index))) {
                    log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                                jobid_2string(base->jobid, strJobId), "xdr_int", "coreindex");
                    quickpool_errno = ERROR_XDR;
                    return FALSE;
                }
            }            
        } else if (XDR_DECODE == xdrs->x_op && 0 < numCore) {
            unsigned int j;

            for (j=0; j<numCore; j++) {
                struct usedCoreInfoDown *core;
                core = (struct usedCoreInfoDown *)calloc(1, sizeof(struct usedCoreInfoDown));
                if (NULL == core) {
                    log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                                sizeof(struct usedCoreInfoDown));
                    quickpool_errno = ERROR_MEMORY;
                    return FALSE;
                }

                if (!xdr_int(xdrs, &(core->index))) {
                    log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                                jobid_2string(base->jobid, strJobId), "xdr_int", "coreindex");
                    quickpool_errno = ERROR_XDR;
                    return FALSE;
                }

                gf_list_insert(execInfo->alloc_cores, execInfo->alloc_cores->forw, (LIST_T *)core);
            }
        }

        if (XDR_DECODE == xdrs->x_op && 0 < numGpu) {

            execInfo->alloc_gpus = gf_list_make("job allocate gpu list");
            if (NULL == execInfo->alloc_gpus) {
                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc", numGpu);
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }
        }

        if (XDR_ENCODE == xdrs->x_op && 0 < numGpu) {
            struct usedGpuIndex *index;
            for (index = (struct usedGpuIndex *)execInfo->alloc_gpus->back; 
                 index != (struct usedGpuIndex *)execInfo->alloc_gpus;
                 index = (struct usedGpuIndex *)index->back) {

                if (!xdr_int(xdrs, &(index->gpu_index))) {
                    log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                                jobid_2string(base->jobid, strJobId), "xdr_int", "gpu_index");
                    quickpool_errno = ERROR_XDR;
                    return FALSE;
                }
            }
        } else if (XDR_DECODE == xdrs->x_op && 0 < numGpu) {
            unsigned int j;

            for (j=0; j<numGpu; j++) {

                struct usedGpuIndex *index;
                index = (struct usedGpuIndex *)calloc(1, sizeof(struct usedGpuIndex));
                if (NULL == index) {
                    log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                                sizeof(struct usedGpuIndex));
                    quickpool_errno = ERROR_MEMORY;
                    return FALSE;
                }

                if (!xdr_int(xdrs, &(index->gpu_index))) {
                    log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                                jobid_2string(base->jobid, strJobId), "xdr_int", "gpu_index");
                    quickpool_errno = ERROR_XDR;
                    return FALSE;
                }

                gf_list_insert(execInfo->alloc_gpus, execInfo->alloc_gpus->forw, (LIST_T *)index);
            }
        }
    }

    if (!(xdr_int(xdrs, (int *)&base->membind_type) && xdr_int(xdrs, &base->gpu_exclusive))) {

        log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                    jobid_2string(base->jobid, strJobId), "xdr_int", "membind_type");
        quickpool_errno = ERROR_XDR;
	return FALSE;
    }

    if (!libxdr_thresholds(xdrs, &(base->thresholds), hdr, NULL)) {
        log_message(ERR, NOCLASS, STR_JOB_FAIL_S, __func__, 
                    jobid_2string(base->jobid, strJobId), "libxdr_thresholds");
        return FALSE;
    }

    if (!xdr_u_int(xdrs, &base->num_exec_files)) {
        log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                    jobid_2string(base->jobid, strJobId), "xdr_u_int", "num_exec_files");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < base->num_exec_files) {

        base->exec_files = (struct execution_file *)calloc(base->num_exec_files,
                                                           sizeof(struct execution_file));
        if (NULL == base->exec_files) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc", base->num_exec_files);
            base->number_node = 0;
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<base->num_exec_files; i++) {

        if (!gf_xdr_element(xdrs, &(base->exec_files[i]), hdr, xdr_execution_file, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(exec_files)", i);
            if (XDR_DECODE == xdrs->x_op) {
                base->num_exec_files = 0;
            }
            quickpool_errno = ERROR_XDR;

	    return FALSE;
	}
    }

    if (!(gf_xdr_string(xdrs, &(base->prequeue_command), hdr, NULL)
          && gf_xdr_string(xdrs, &(base->postqueue_command), hdr, NULL)
          && gf_xdr_string(xdrs, &(base->run_window), hdr, NULL)
          && gf_xdr_string(xdrs, &(base->execute_cwd), hdr, NULL)
          && gf_xdr_string(xdrs, &(base->execute_home), hdr, NULL)
          && gf_xdr_string(xdrs, &(base->requeue_exitcode), hdr, NULL)
          && gf_xdr_string(xdrs, &(base->resume_condition), hdr, NULL)
          && gf_xdr_string(xdrs, &(base->stop_condition), hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                    jobid_2string(base->jobid, strJobId), "gf_xdr_string", "prequeue_command");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(xdr_int(xdrs, (int *)&base->execute_uid) && xdr_u_int(xdrs, &base->num_environment))) {

        log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                    jobid_2string(base->jobid, strJobId), "xdr_int", "execute_uid");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < base->num_environment) {

        base->environment = (char **)calloc(base->num_environment, sizeof(char *));
        if (NULL == base->environment) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc", base->num_environment);
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<base->num_environment; i++) {

        if (!gf_xdr_string(xdrs, &(base->environment[i]), hdr, NULL)) {
            log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                        jobid_2string(base->jobid, strJobId), "gf_xdr_string", "environment");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (!xdr_file_data(xdrs, &base->eexec, hdr, argument)) {
        log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                    jobid_2string(base->jobid, strJobId), "xdr_file_data", "eexec");
        return FALSE;
    }

    if (!(gf_xdr_string(xdrs, &(base->suspend_command), hdr, NULL)
          && gf_xdr_string(xdrs, &(base->resume_command), hdr, NULL)
          && gf_xdr_string(xdrs, &(base->terminate_command), hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                    jobid_2string(base->jobid, strJobId), "gf_xdr_string", "suspend_command");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    for (i = 0; i <QUICKPOOL_SIGNAL_NUMBER; i++) {

        if (!(xdr_int(xdrs, &base->quickpool_signal[i]))) {
            log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                        jobid_2string(base->jobid, strJobId), "xdr_int", "quickpool_signal");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (!(xdr_int(xdrs, &base->act_signal))) {
        log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                    jobid_2string(base->jobid, strJobId), "xdr_int", "act_signal");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(gf_xdr_string(xdrs, &(base->schedule_host), hdr, NULL)
          && gf_xdr_string(xdrs, &(base->prepost_user), hdr, NULL)
          && gf_xdr_string(xdrs, &(base->execute_user), hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                    jobid_2string(base->jobid, strJobId), "gf_xdr_string", "schedule_host");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!xdr_file_data(xdrs, &base->job_file, hdr, argument)) {
        log_message(ERR, NOCLASS, STR_JOB_FAIL_S_S, __func__,
                    jobid_2string(base->jobid, strJobId), "xdr_file_data", "job_file");
        return FALSE;
    }

    return TRUE;
} // end function libxdr_jobbase

/**
 * @brief       XDR: xdr function to exchange jm package between JM and JS.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   jmpack          #2: jm package to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
xdr_jm_package(XDR *xdrs, void *jmpack, struct header *hdr, void *argument)
{
    unsigned int i;
    struct jmPackage *package = (struct jmPackage *)jmpack;

    if (xdrs->x_op == XDR_FREE) {

        for (i = 0; i < package->num_admin; i++) {
	    FREEUP(package->admins[i]);
        }
	FREEUP(package->admins);

        FREEUP(package->base_jobinfo);

        free_param_value(package->jm_params);
        for (i=0; i<package->num_param; i++) {
            if (NULL != package->jm_params[i].param_name) {
                free((char *)package->jm_params[i].param_name);
            }
        }
        FREEUP(package->jm_params);

        return TRUE;
    }

    if (!xdr_u_int(xdrs, &package->num_param)) {
        quickpool_errno = ERROR_XDR;
        log_message(ERR, NOCLASS, STR_FUNC_S_FAIL, __func__, "xdr_int", "num_param");
	return FALSE;
    }

    if (xdrs->x_op == XDR_DECODE && package->num_param > 0) {

        package->jm_params = (struct config_param *)calloc(package->num_param+1,
                                                           sizeof(struct config_param));
        if (NULL == package->jm_params) {
            quickpool_errno = ERROR_MEMORY;
            log_message(ERR, NOCLASS, "%s: calloc(%d) failed: %m", __func__, package->num_param+1);
            return FALSE;
	}
    }

    for (i = 0; i < package->num_param; i++) {
        if (!(gf_xdr_string(xdrs, &package->jm_params[i].param_name, hdr, NULL)
              && xdr_int(xdrs, (int *)(&package->jm_params[i].param_type))
              && xdr_int(xdrs, &package->jm_params[i].index))) {

            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(param_name)");
            return FALSE;
        }

        switch (package->jm_params[i].param_type) {
        case INT_PARAM:
            if (!xdr_int(xdrs, &package->jm_params[i].int_value)) {
                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(int_value)");
                return FALSE;
            }
            break;
        case BOOL_PARAM:
            if (!xdr_int(xdrs, &package->jm_params[i].bool_value)) {
                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(bool_value)");
                return FALSE;
            }
            break;
        case STRING_PARAM:
            if (!gf_xdr_string(xdrs, &package->jm_params[i].string_value, hdr, NULL)) {
                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(string_value)");
                return FALSE;
            }
            break;
        case FLOAT_PARAM:
            if (!xdr_double(xdrs, &package->jm_params[i].float_value)) {
                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_double(float_value)");
                return FALSE;
            }
            break;
        }
    }

    if (xdrs->x_op == XDR_DECODE && package->num_param > 0) {
        package->jm_params[package->num_param].param_name = NULL;
        package->jm_params[package->num_param].param_type = STRING_PARAM;
    }

    if (!xdr_int(xdrs, &package->js_pid)) {
        log_message(ERR, NOCLASS, STR_FUNC_S_FAIL, __func__, "xdr_int", "num_param");
        quickpool_errno = ERROR_XDR;
	return FALSE;
    }

    if (!xdr_u_int(xdrs, &package->num_admin)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_admin)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < package->num_admin) {
        package->admins = (char **)calloc(package->num_admin, sizeof(char *));
        if (NULL == package->admins) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", package->num_admin*sizeof(char *));
            package->num_admin = 0;
            return FALSE;
        }
    }

    for (i = 0; i < package->num_admin; i++) {

        if (!gf_xdr_string(xdrs, &(package->admins[i]), hdr, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_string(admins)", i);
            if (XDR_DECODE == xdrs->x_op) {
                package->num_admin = i;
            }
            quickpool_errno = ERROR_XDR;

            return FALSE;
        }
    }

    if (!xdr_u_int(xdrs, &package->num_job)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_job)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (xdrs->x_op == XDR_DECODE && package->num_job > 0) {
        package->base_jobinfo = (struct jobInfo *)calloc(package->num_job,
                                                         sizeof(struct jobInfo));
        if (NULL == package->base_jobinfo) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", package->num_job*sizeof(struct jobInfo));
            package->num_job = 0;
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i = 0; i < package->num_job; i++) {

        if (!gf_xdr_element(xdrs, &(package->base_jobinfo[i]), hdr, libxdr_jobbase, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(jobinfo)", i);
            if (XDR_DECODE == xdrs->x_op) {
                package->num_job = i;
            }

            return FALSE;
        }
    }

    return TRUE;
} // end function xdr_jm_package

/**
 * @brief       XDR: xdr function to exchange job thresholds.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   jobthresholds   #2: job thresholds to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
int
libxdr_thresholds(XDR *xdrs, void *jobthresholds, struct header *hdr, void *argument)
{
    struct thresholds *thresholds = (struct thresholds *)jobthresholds;

    unsigned int i, j;
    if (XDR_FREE == xdrs->x_op) {

        for(i=0; i<thresholds->num_threshold; i++) {
            FREEUP(thresholds->load_schedule[i]);
            FREEUP(thresholds->load_stop[i]);
        }

        FREEUP(thresholds->load_schedule);
        FREEUP(thresholds->load_stop);

        return TRUE;
    }

    if (!(xdr_u_int(xdrs, &thresholds->num_index)
          && xdr_u_int(xdrs, &thresholds->num_threshold))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL_S, __func__, "xdr_int", "num_index");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < thresholds->num_threshold && 0 < thresholds->num_index) {

        thresholds->load_schedule = (float **)calloc(thresholds->num_threshold, sizeof(float *));
	thresholds->load_stop = (float **)calloc(thresholds->num_threshold, sizeof(float *));
        if (NULL == thresholds->load_schedule || NULL == thresholds->load_stop) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", thresholds->num_threshold*2*sizeof(float *));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }

        for (i=0; i<thresholds->num_threshold; i++) {

            thresholds->load_schedule[i] = (float *)calloc(thresholds->num_index, sizeof(float));
            thresholds->load_stop[i] = (float *)calloc(thresholds->num_index, sizeof(float));

            if (NULL == thresholds->load_schedule[i] || NULL == thresholds->load_stop[i]) {

                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                            "calloc", thresholds->num_index*2*sizeof(float));
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }
        }
    }

    for (i=0; i<thresholds->num_threshold; i++) {

        for (j=0; j<thresholds->num_index; j++) {

            if (!(xdr_float(xdrs, &(thresholds->load_stop[i][j]))
	          && xdr_float(xdrs, &(thresholds->load_schedule[i][j])))) {

                log_message(ERR, NOCLASS, STR_FUNC_FAIL_S, __func__, "xdr_float","load_stop");
                quickpool_errno = ERROR_XDR;
                return FALSE;
            }
	}
    }

    return TRUE;
} // end function libxdr_thresholds

/**
 * @brief       XDR: xdr function to exchange node numa information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   numaobj         #2: node numa object
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
xdr_numainfo(XDR *xdrs, void *numaobj, struct header *hdr, void *arguments)
{
    numa_obj_t *numa = (numa_obj_t *)numaobj;
    
    numa_obj_t *childObj=NULL;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == numa) {
            return (TRUE);
        }

        numa_obj_t *nextObj = NULL;
        childObj = numa->child;
        for (; childObj != NULL; childObj = nextObj) {

            if (NUMA_CORE == childObj->type) {
                nextObj = childObj->back;
                FREEUP(childObj);
            } else {
                nextObj = childObj->back;
                xdr_numainfo(xdrs, (void *)childObj, hdr, NULL);
               
            }
        }  
        FREEUP(numa);

        return (TRUE);
    }

    if (!(xdr_int(xdrs, &numa->type))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(type)");
        return FALSE;        
    }

    if (!(xdr_int(xdrs, &numa->total))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(total)");
        return FALSE;        
    }

    if (!(xdr_int(xdrs, &numa->used))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(used)");
        return FALSE;        
    }

    if (!(xdr_int(xdrs, &numa->bound))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(bound)");
        return FALSE;        
    }

    if (!(xdr_u_int(xdrs, &numa->child_num))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(child_num)");
        return FALSE;        
    }

    if (!(xdr_int(xdrs, &numa->index))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(index)");
        return FALSE;        
    }

    if (!(xdr_int(xdrs, &numa->index_sibling))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(index_sibling)");
        return FALSE;        
    }    
    if (!(xdr_int(xdrs, &numa->memory))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(memory)");
        return FALSE;        
    }    

    if (NUMA_CORE == numa->type) {
        return TRUE;
    } 

    numa_obj_t *tmpObj=NULL;
    unsigned int i;
    for (i = 0; i < numa->child_num; i++) {

        if (XDR_DECODE == xdrs->x_op) {          
            childObj = (numa_obj_t *)calloc(1, sizeof(numa_obj_t));
            if (NULL == childObj) {
                log_message(ERR, NOCLASS, "%s: calloc failed: %m", __func__);
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }  

            if (NULL == numa->child) {
                numa->child = childObj;
                tmpObj = childObj;
            } else {
                tmpObj->back = childObj;
                tmpObj = childObj;
            }  

            childObj->parent = numa;
        }

        if (XDR_ENCODE == xdrs->x_op) {
            if (NULL == childObj) {
                childObj = numa->child;
            } else {
                childObj = childObj->back;
            }
        }        

        xdr_numainfo(xdrs, (void *)childObj, hdr, NULL);
    } 

    return TRUE;
} // end function xdr_numainfo
    
/* ------------------------------------------------
 *
 *  below are static functions used in this file
 *
 * ------------------------------------------------ */

/**
 * @brief       XDR: xdr function to exchange single resource definition.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   resourcedef     #2: single resource definition to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
static bool_t
xdr_resource_definition(XDR *xdrs, void *resourcedef, struct header *hdr, void *argument)
{
    struct resource_definition *def = (struct resource_definition *)resourcedef;

    if (XDR_FREE == xdrs->x_op) {

        FREEUP(def->name);
        FREEUP(def->des);

        return TRUE;
    }

    if (!(gf_xdr_string(xdrs, &(def->name), hdr, NULL)
          && gf_xdr_string(xdrs, &(def->des), hdr, NULL)
          && xdr_enum(xdrs, (int *)&def->value_type)
          && xdr_enum(xdrs, (int *)&def->order_type)
          && xdr_int(xdrs, &def->flags) && xdr_int(xdrs, &def->interval))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(name and so on)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    return TRUE;
} // end function xdr_resource_definition

/**
 * @brief       Calculate size of resource map.
 *
 * @param[in]   map           #1: resource map
 *
 * @retval      >0            #1: size of resource map
 */
static unsigned int
sizeof_resource_map(struct QuickPoolResourceMap *map)
{
    unsigned int len, i;

    len = sizeof(struct QuickPoolResourceMap);

    len += sizeof(int) + strlen(map->total_value) + XDR_OFFSET;
    len += sizeof(int) + strlen(map->reserve_value) + XDR_OFFSET;

    len += sizeof(int);
    for (i = 0; i < map->num_hosts; i++) {
        len += sizeof(int) + strlen(map->hosts[i]) + XDR_OFFSET + 1;
    }

    return len;
} // end function sizeof_resource_map

/**
 * @brief       XDR: xdr function to exchange single resource instance information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   resourceinst    #2: single resource instance information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
static bool_t
xdr_resource_map(XDR *xdrs, void *resourceinst, struct header *hdr, void *argument)
{
    struct QuickPoolResourceMap *instance = (struct QuickPoolResourceMap *)resourceinst;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == instance) {
            return TRUE;
        }

        FREEUP(instance->total_value);
        FREEUP(instance->reserve_value);

        for (i=0; i<instance->num_hosts; i++) {
            FREEUP(instance->hosts[i]);
        }
        FREEUP(instance->hosts);

        return TRUE;
    }

    if (!(gf_xdr_string(xdrs, &(instance->total_value), hdr, NULL)
          && gf_xdr_string(xdrs, &(instance->reserve_value), hdr, NULL)
          && xdr_u_int(xdrs, &instance->num_hosts))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(values)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < instance->num_hosts) {

        instance->hosts = (char **)calloc(instance->num_hosts, sizeof(char *));
        if (NULL == instance->hosts) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc", instance->num_hosts);
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<instance->num_hosts; i++) {

        if (!gf_xdr_string(xdrs, &(instance->hosts[i]), hdr, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_string(hosts)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    return TRUE;
} // end function xdr_resource_map

/**
 * @brief       Calculate size of resource info.
 *
 * @param[in]   info          #1: resource info
 *
 * @retval      >0            #1: size of resource info
 */
static unsigned int
sizeof_resource_info(struct QuickPoolResourceInfo *info)
{
    unsigned int len, i;

    len = sizeof(struct QuickPoolResourceInfo);

    len += sizeof(int) + strlen(info->resource_name) + XDR_OFFSET;

    len += sizeof(int);
    for (i = 0; i < info->num_instances; i++) {
        len += sizeof_resource_map(&(info->instances[i]));
    }

    return len;
} // end function sizeof_resource_info

/**
 * @brief       XDR: xdr function to exchange single resource information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   resourceinfo    #2: single resource information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
static bool_t
xdr_resource_info(XDR *xdrs, void *resourceinfo, struct header *hdr, void *argument)
{
    struct QuickPoolResourceInfo *info = (struct QuickPoolResourceInfo *)resourceinfo;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == info) {
            return TRUE;
        }

        FREEUP(info->resource_name);
        for (i=0; i<info->num_instances; i++) {
            gf_xdr_free(xdr_resource_map, &(info->instances[i]));
        }
        FREEUP(info->instances);

        return TRUE;
    }

    if (!(gf_xdr_string(xdrs, &(info->resource_name), hdr, NULL)
          && xdr_u_int(xdrs, &info->flags)
          && xdr_u_int(xdrs, &info->num_instances))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(resource_name)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < info->num_instances) {

        info->instances = (struct QuickPoolResourceMap *)calloc(info->num_instances,
                                                                sizeof(struct QuickPoolResourceMap));
        if (NULL == info->instances) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        info->num_instances*sizeof(struct QuickPoolResourceMap));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<info->num_instances; i++) {

        if (!gf_xdr_element(xdrs, (void *)&info->instances[i], hdr, xdr_resource_map, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_element(instances)", i);
            info->num_instances = i;
            return FALSE;
        }
    }

    return TRUE;
} // end function xdr_resource_info

/**
 * @brief       XDR: xdr function to exchange single cluster information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   clusterinfo     #2: single cluster information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
static bool_t
xdr_cluster_info(XDR *xdrs, void *clusterinfo, struct header *hdr, void *argument)
{
    struct QuickPoolClusterInfo *info = (struct QuickPoolClusterInfo *)clusterinfo;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == info) {
            return TRUE;
        }

        for (i=0; i<info->num_admins; i++) {
            FREEUP(info->admins[i]);
        }
        FREEUP(info->admins);
        FREEUP(info->admin_ids);

        for (i=0; i<info->num_resources; i++) {
            FREEUP(info->resource_names[i]);
        }
        FREEUP(info->resource_names);

        for (i=0; i<info->num_types; i++) {
            FREEUP(info->host_types[i]);
        }
        FREEUP(info->host_types);

        for (i=0; i<info->num_models; i++) {
            FREEUP(info->host_models[i]);
        }
        FREEUP(info->host_models);

        return TRUE;
    }

    char *sp = info->cluster_name;
    if (!gf_xdr_string(xdrs, &(sp), hdr, NULL)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(cluster_name)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    sp = info->master_name;
    if (!gf_xdr_string(xdrs, &(sp), hdr, NULL)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(master_name)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    sp = info->manager_name;
    if (!gf_xdr_string(xdrs, &(sp), hdr, NULL)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(manager_name)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(xdr_int(xdrs, &info->status)
          && xdr_int(xdrs, &info->num_servers)
          && xdr_int(xdrs, &info->num_clients)
          && xdr_u_int(xdrs, &info->manager_id)
          && xdr_u_int(xdrs, &info->num_admins))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(status and so on)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < info->num_admins) {

        info->admins = (char **)calloc(info->num_admins, sizeof(char *));
        info->admin_ids = (uid_t *)calloc(info->num_admins, sizeof(uid_t));
        if (NULL == info->admins || NULL == info->admin_ids) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        info->num_admins*sizeof(char *));
            quickpool_errno = ERROR_MEMORY;
            info->num_admins = 0;
            return FALSE;
        }
    }

    for (i = 0; i < info->num_admins; i++) {

        if (!(gf_xdr_string(xdrs, &(info->admins[i]), hdr, NULL)
              && xdr_u_int(xdrs, &info->admin_ids[i]))) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "gf_xdr_string(admins)", i);
            quickpool_errno = ERROR_XDR;
            info->num_admins = i;
            return FALSE;
        }
    }

    if (!xdr_u_int(xdrs, &info->num_resources)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_resources)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < info->num_resources) {

        info->resource_names = (char **)calloc(info->num_resources, sizeof(char *));
        if (NULL == info->resource_names) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        info->num_resources*sizeof(char *));
            quickpool_errno = ERROR_MEMORY;
            info->num_resources = 0;
            return FALSE;
        }
    }

    for (i = 0; i < info->num_resources; i++) {

        if (!(gf_xdr_string(xdrs, &(info->resource_names[i]), hdr, NULL))) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__,
                        "gf_xdr_string(resource_names)", i);
            quickpool_errno = ERROR_XDR;
            info->num_resources = i;
            return FALSE;
        }
    }

    if (!xdr_u_int(xdrs, &info->num_types)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_types)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < info->num_types) {

        info->host_types = (char **)calloc(info->num_types, sizeof(char *));
        if (NULL == info->host_types) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        info->num_types*sizeof(char *));
            quickpool_errno = ERROR_MEMORY;
            info->num_types = 0;
            return FALSE;
        }
    }

    for (i = 0;  i < info->num_types; i++) {

        if (!(gf_xdr_string(xdrs, &(info->host_types[i]), hdr, NULL))) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__,
                        "gf_xdr_string(host_types)", i);
            quickpool_errno = ERROR_XDR;
            info->num_types = i;
            return FALSE;
        }
    }

    if (!xdr_u_int(xdrs, &info->num_models)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_models)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < info->num_models) {

        info->host_models = (char **)calloc(info->num_models, sizeof(char *));
        if (NULL == info->host_models) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        info->num_models*sizeof(char *));
            quickpool_errno = ERROR_MEMORY;
            info->num_models = 0;
            return FALSE;
        }
    }

    for (i = 0; i < info->num_models; i++) {

        if (!(gf_xdr_string(xdrs, &(info->host_models[i]), hdr, NULL))) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__,
                        "gf_xdr_string(host_models)", i);
            quickpool_errno = ERROR_XDR;
            info->num_models = i;
            return FALSE;
        }
    }

    return TRUE;
} // end function xdr_cluster_info

/**
 * @brief       XDR: xdr function to exchange resource limits.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   resourcelimits  #2: resource limits to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
static bool_t
xdr_resource_limit(XDR *xdrs, void *resourcelimits, struct header *hdr, void *argument)
{
    struct resourceLimit *limits = (struct resourceLimit *)resourcelimits;

    if (!(xdr_u_int(xdrs, (unsigned int*)&limits->rlim_curl)
          && xdr_u_int(xdrs, (unsigned int*)&limits->rlim_curh)
          && xdr_u_int(xdrs, (unsigned int*)&limits->rlim_maxl)
          && xdr_u_int(xdrs, (unsigned int*)&limits->rlim_maxh))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(limits)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    return TRUE;
} // end function xdr_resource_limit

static bool_t
xdr_single_share(XDR *xdrs, void *shareacct, struct header *hdr, void *argument)
{
    struct share_acct *ssa = (struct share_acct *)shareacct;

    if (XDR_FREE == xdrs->x_op) {

        if (NULL == ssa) {
            return TRUE;
        }

        FREEUP(ssa->name);

        return TRUE;
    }

    if (!(gf_xdr_string(xdrs, &ssa->name, hdr, NULL) && xdr_u_int(xdrs, &ssa->shares)
          && xdr_double(xdrs, &ssa->dshares) && xdr_u_int(xdrs, &ssa->numPEND)
          && xdr_u_int(xdrs, &ssa->numRUN) && xdr_u_int(xdrs, &ssa->options)
          && xdr_u_int(xdrs, &ssa->numBORROWED))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(share_acct)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    return TRUE;
} // end function xdr_single_share

/**
 * @brief       XDR: xdr function to exchange queue fairshare tree.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   num             #2: number of share account
 * @param[in|out]   s               #3: share account
 * @param[in]       hdr             #4: XDR header
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
static bool_t
xdr_share_accounts(XDR *xdrs, unsigned int *num, struct share_acct ***sa, struct header *hdr)
{
    unsigned int i;

    if (!xdr_u_int(xdrs, num)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(limits)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    struct share_acct **sab = NULL;
    if (XDR_ENCODE == xdrs->x_op) {
        sab = *sa;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < *num) {

        sab = (struct share_acct **)calloc(*num, sizeof(struct share_acct *));
        if (NULL == sab) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        *num*sizeof(struct share_acct *));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i=0; i<*num; i++) {

        if (XDR_DECODE == xdrs->x_op) {

            sab[i] = (struct share_acct *)calloc(1, sizeof(struct share_acct));
            if (NULL == sab[i]) {
                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                            sizeof(struct share_acct));
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }
        }

        if (!xdr_single_share(xdrs, sab[i], hdr, NULL)) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__,
                        "xdr_single_share", i);
            if (XDR_DECODE == xdrs->x_op) {
                *num = i;
            }
            return FALSE;
        }
    }

    if (XDR_DECODE == xdrs->x_op) {
        *sa = sab;
    }

    return TRUE;
} // end function xdr_share_accounts

/**
 * @brief       XDR: xdr function to exchange single queue information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   queueinfo       #2: single queue information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
static bool_t
xdr_queue_info(XDR *xdrs, void *queueinfo, struct header *hdr, void *argument)
{
    struct QuickPoolQueueInfo *info = (struct QuickPoolQueueInfo *)queueinfo;
    unsigned int *numIndicies = (unsigned int *)argument;

    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        if (NULL == info) {
            return TRUE;
        }

        FREEUP(info->queue);
        FREEUP(info->description);
        FREEUP(info->users);
        FREEUP(info->hosts);
        FREEUP(info->run_window);
        FREEUP(info->dispatch_window);
        FREEUP(info->administrators);
        FREEUP(info->prejob_command);
        FREEUP(info->postjob_command);
        FREEUP(info->prepost_user);
        FREEUP(info->requeue_exitcode);
        FREEUP(info->resource_requirement);
        FREEUP(info->resume_condition);
        FREEUP(info->stop_condition);
        FREEUP(info->job_starter);
        FREEUP(info->suspend_command);
        FREEUP(info->resume_command);
        FREEUP(info->terminate_command);
        FREEUP(info->chkpnt_dir);
        FREEUP(info->preemption);
        FREEUP(info->load_schedule);
        FREEUP(info->load_stop);

        for (i=0; i<info->num_fairshare_account; i++) {
            gf_xdr_free(xdr_single_share, (void *)((info->fairshare_accounts)[i]));
            FREEUP(info->fairshare_accounts[i]);
        }
        FREEUP(info->fairshare_accounts);

        return TRUE;
    }

    if (!(gf_xdr_string(xdrs, &info->queue, hdr, NULL)
          && gf_xdr_string(xdrs, &info->description, hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_string(queue, description)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(gf_xdr_string(xdrs, &info->users, hdr, NULL))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(users)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(gf_xdr_string(xdrs, &info->hosts, hdr, NULL))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(hosts)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(gf_xdr_string(xdrs, &info->run_window, hdr, NULL))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(run_window)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    for(i = 0; i < RESOURCE_LIMIT_NUM; i++) {
        if (!(xdr_int(xdrs, &info->queue_ulimit[i]))) {
            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(queue_ulimit)");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }

        if (!(xdr_int(xdrs, &info->default_ulimit[i]))) {
            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(default_ulimit)");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (XDR_DECODE == xdrs->x_op && 0 < *numIndicies) {

        info->load_schedule = (float *)calloc(*numIndicies, sizeof(float));
        info->load_stop = (float *)calloc(*numIndicies, sizeof(float));
        if (NULL == info->load_schedule || NULL == info->load_stop) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                        "calloc", *numIndicies*sizeof(float)*2);
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i = 0; i < *numIndicies; i++) {

        if (!(xdr_float(xdrs, &(info->load_schedule[i]))
              && xdr_float(xdrs, &(info->load_stop[i])))) {

            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_float(loadSced, loadStop)");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (!(xdr_int(xdrs, &info->priority) && xdr_short(xdrs, &info->nice)
          && xdr_u_int(xdrs, &info->user_slot_limit)
          && xdr_int(xdrs, &info->schedule_policy) && xdr_int(xdrs, &info->queue_status)
          && xdr_u_int(xdrs, &info->max_num_slot) && xdr_u_int(xdrs, &info->num_job_slot)
          && xdr_u_int(xdrs, &info->num_pending_slot) && xdr_u_int(xdrs, &info->num_running_slot)
          && xdr_u_int(xdrs, &info->num_SSUSP_slot) && xdr_u_int(xdrs, &info->num_USUSP_slot)
          && xdr_int(xdrs, &info->mig) && xdr_int(xdrs, &info->job_dispatch_interval)
          && xdr_u_int(xdrs, &info->num_reserving_slot)
          && xdr_int(xdrs, &info->job_schedule_delay))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(priority and so on)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(gf_xdr_string(xdrs, &info->dispatch_window, hdr, NULL))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(dispatch_window)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(xdr_u_int(xdrs, &info->job_slot_limit)
          && gf_xdr_string(xdrs, &info->administrators, hdr, NULL)
          && gf_xdr_string(xdrs, &info->prejob_command, hdr, NULL)
          && gf_xdr_string(xdrs, &info->postjob_command, hdr, NULL)
          && gf_xdr_string(xdrs, &info->prepost_user, hdr, NULL)
          && gf_xdr_string(xdrs, &info->requeue_exitcode, hdr, NULL)
          && xdr_u_int(xdrs, &info->host_slot_limit))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(job_slot_limit and so on)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(gf_xdr_string(xdrs, &info->resource_requirement, hdr, NULL)
          && xdr_int(xdrs, &info->reservation_time)
          && gf_xdr_string(xdrs, &info->resume_condition, hdr, NULL)
          && gf_xdr_string(xdrs, &info->stop_condition, hdr, NULL)
          && gf_xdr_string(xdrs, &info->job_starter, hdr, NULL)
          && gf_xdr_string(xdrs, &info->suspend_command, hdr, NULL)
          && gf_xdr_string(xdrs, &info->resume_command, hdr, NULL)
          &&gf_xdr_string(xdrs, &info->terminate_command, hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(resource_requirement)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    for (i=0; i<QUICKPOOL_SIGNAL_NUMBER; i++) {

        if (!xdr_int(xdrs, &info->quickpool_signal[i])) {
            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(quickpool_signal)");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (!(xdr_u_int (xdrs, &info->min_job_slot)
          && xdr_u_int(xdrs, &info->default_job_slot))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(min_job_slot)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!xdr_share_accounts(xdrs, &info->num_fairshare_account, &info->fairshare_accounts, hdr)) {
        return FALSE;
    }

    if (!xdr_u_int(xdrs, &info->num_fairshare_slot)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_fairshare_slot)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!gf_xdr_string(xdrs, &info->preemption, hdr, NULL)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(preemption)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!xdr_u_int(xdrs, &info->num_owned_slots)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_owned_slots)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(gf_xdr_string(xdrs, &info->chkpnt_dir, hdr, NULL)
          && xdr_int(xdrs, &info->chkpnt_period))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(chkpnt_dir)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    return TRUE;
} // end function xdr_queue_info

/**
 * @brief       XDR: xdr function to exchange single host information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   hostinfo        #2: single host information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
static bool_t
xdr_host_info(XDR *xdrs, void *hostinfo, struct header *hdr, void *argument)
{
    struct QuickPoolHostInfo *info = (struct QuickPoolHostInfo *)hostinfo;
    unsigned int i;
    unsigned int *numIndicies = (unsigned int *)argument;
    int numaFlag = 0;

    if (XDR_FREE == xdrs->x_op) {

        if (NULL == info) {
            return TRUE;
        }

        FREEUP(info->host);
        FREEUP(info->dispatch_window);
        FREEUP(info->host_type);
        FREEUP(info->host_model);
        FREEUP(info->load_threshold);
        FREEUP(info->res_bitmap);
        FREEUP(info->busy_schedule);
        FREEUP(info->busy_stop);
        FREEUP(info->load_schedule);
        FREEUP(info->load_stop);
        FREEUP(info->real_load);
        FREEUP(info->load);
        xdr_numainfo(xdrs,(void *)(info->numa), hdr, NULL);

        for (i = 0; i < info->num_GPU; i++) {
            FREEUP(info->gpuinfo_static[i].gpu_model);
            if (NULL != info->gpuinfo_dynamic) {
                FREEUP(info->gpuinfo_dynamic[i].status);
                FREEUP(info->gpuinfo_dynamic[i].error);
                FREEUP(info->gpuinfo_dynamic[i].jobids);
            }
        }
        FREEUP(info->gpuinfo_static);
        FREEUP(info->gpuinfo_dynamic);

        return TRUE;
    }

    if (!(gf_xdr_string(xdrs, &info->host, hdr, NULL)
          && gf_xdr_string(xdrs, &info->dispatch_window, hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_string(host window)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(gf_xdr_string(xdrs, &info->host_type, hdr, NULL)
          && gf_xdr_string(xdrs, &info->host_model, hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(hostType/hostModel)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!xdr_u_int(xdrs, &info->num_GPU)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(countGPU and so on)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < info->num_GPU) {

        info->gpuinfo_static = (struct hostGPUList *)calloc(info->num_GPU,
                                                             sizeof(struct hostGPUList));
        if (NULL == info->gpuinfo_static) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        info->num_GPU*(sizeof(struct hostGPUList)));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    for (i = 0; i < info->num_GPU; i++) {

        if (!(xdr_int(xdrs, &(info->gpuinfo_static[i].gpu_id))
              && xdr_double(xdrs, &(info->gpuinfo_static[i].gpu_maxmem))
              && xdr_float(xdrs, &(info->gpuinfo_static[i].gpu_factor))
              && gf_xdr_string(xdrs, &(info->gpuinfo_static[i].gpu_model), hdr, NULL))) {

            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(gpuinfo_static)");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    if (XDR_ENCODE == xdrs->x_op && NULL != info->numa) {
        numaFlag = 1;
    }

    if (!xdr_int(xdrs, &numaFlag)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(numaFlag)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }
    
    if (XDR_DECODE == xdrs->x_op && 0 < numaFlag) {

        info->numa = (numa_obj_t *)calloc(1, sizeof(numa_obj_t));
        if (NULL == info->numa) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc", sizeof(numa_obj_t));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    if (0 < numaFlag && NULL != info->numa) {

        if (!gf_xdr_element(xdrs, (void *)info->numa, hdr, xdr_numainfo, NULL)) {
            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_element(numainfo)");
            return FALSE;
        }
    }

    if (!(xdr_int(xdrs, &info->flags) && xdr_int(xdrs, &info->max_jobs))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(flags)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (info->flags & HOSTINFO_JM_INFO) {
        if (!(xdr_double(xdrs, &info->maxmem) && xdr_double(xdrs, &info->maxswap)
              && xdr_double(xdrs, &info->maxtmp) && xdr_int(xdrs, &info->ncpus)
              && xdr_short(xdrs, (short *)&info->server))) {

            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_long(maxmem and so on)");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }

        if (XDR_DECODE == xdrs->x_op && 0 < *numIndicies) {

            info->load_threshold = (double *)calloc(*numIndicies, sizeof(double));
            info->res_bitmap = (int *)calloc(GET_INTNUM (*numIndicies), sizeof(int));
            if (NULL == info->load_threshold || NULL == info->res_bitmap) {

                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                            "calloc", *numIndicies*sizeof(double));
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }
        }

        for(i=0; i < *numIndicies; i++) {

            if (!xdr_double(xdrs, &info->load_threshold[i])) {
                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_float(load_threshold)");
                quickpool_errno = ERROR_XDR;
                return FALSE;
            }
        }

        for (i = 0; i < GET_INTNUM (*numIndicies); i++) {

            if (!xdr_int(xdrs, &info->res_bitmap[i])) {
                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(res_bitmap)");
                quickpool_errno = ERROR_XDR;
                return FALSE;
            }
        }
    } else {
        if (!(xdr_u_int(xdrs, &info->user_slot_limit) && xdr_int(xdrs, &info->attr)
              && xdr_u_int(xdrs, &info->num_job_slot) && xdr_u_int(xdrs, &info->num_running_slot)
              && xdr_u_int(xdrs, &info->num_SSUSP_slot) && xdr_u_int(xdrs, &info->num_USUSP_slot)
              && xdr_u_int(xdrs, &info->num_reserving_slot)
              && xdr_int(xdrs, &info->status) && xdr_int(xdrs, &info->mig))) {

            log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(max_jobs and so on)");
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }

        if (XDR_DECODE == xdrs->x_op && 0 < *numIndicies) {

            info->busy_schedule = (int *)calloc(GET_INTNUM(*numIndicies), sizeof(int));
            info->busy_stop = (int *)calloc(GET_INTNUM(*numIndicies), sizeof(int));
            if (NULL == info->busy_schedule || NULL == info->busy_stop) {

                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                            "calloc", GET_INTNUM(*numIndicies)*sizeof(int)*2);
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }
        }

        for (i = 0; i < GET_INTNUM (*numIndicies); i++) {

            if (!(xdr_int(xdrs, &info->busy_schedule[i])
                && xdr_int(xdrs, &info->busy_stop[i]))) {

                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(busySched, busyStop)");
                quickpool_errno = ERROR_XDR;
                return FALSE;
            }
        }

        if (XDR_DECODE == xdrs->x_op && 0 < *numIndicies) {

            info->load_schedule = (float *)calloc(*numIndicies, sizeof(float));
            info->load_stop = (float *)calloc(*numIndicies, sizeof(float));
            if (NULL == info->load_schedule || NULL == info->load_stop) {

                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                            "calloc", *numIndicies*sizeof(float)*2);
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }

            info->real_load = (double *)calloc(*numIndicies, sizeof(double));
            info->load = (double *)calloc(*numIndicies, sizeof(double));

            if (NULL == info->real_load || NULL == info->load) {

                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__,
                            "calloc", *numIndicies*sizeof(double)*2);
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }
        }

        for (i = 0; i < *numIndicies; i++) {

            if (!(xdr_float(xdrs, &info->load_schedule[i])
                  && xdr_float(xdrs, &info->load_stop[i]))) {

                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_float(loadSched, loadStop)");
                quickpool_errno = ERROR_XDR;
                return FALSE;
            }

            if (!(xdr_double(xdrs, &info->real_load[i])
                  && xdr_double(xdrs, &info->load[i]))) {

                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_double(load, real_load)");
                quickpool_errno = ERROR_XDR;
                return FALSE;
            }
        }

        if (XDR_DECODE == xdrs->x_op && 0 < info->num_GPU) {

            info->gpuinfo_dynamic = (struct hostGPULoad *)calloc(info->num_GPU,
                                                                 sizeof(struct hostGPULoad));
            if (NULL == info->gpuinfo_dynamic) {

                log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                            info->num_GPU*(sizeof(struct hostGPULoad)));
                quickpool_errno = ERROR_MEMORY;
                return FALSE;
            }
        }

        for (i = 0; i < info->num_GPU; i++) {

            if (!(xdr_int(xdrs, &(info->gpuinfo_dynamic[i].gpu_id))
                  && xdr_float(xdrs, &(info->gpuinfo_dynamic[i].gpu_ut))
                  && xdr_double(xdrs, &(info->gpuinfo_dynamic[i].avail_gpu_mem))
                  && xdr_int(xdrs, &(info->gpuinfo_dynamic[i].gpu_mode))
                  && gf_xdr_string(xdrs, &(info->gpuinfo_dynamic[i].status), hdr, NULL)
                  && xdr_u_int(xdrs, &(info->gpuinfo_dynamic[i].gpu_temperature))
                  && xdr_int(xdrs, &(info->gpuinfo_dynamic[i].num_job))
                  && gf_xdr_string(xdrs, &(info->gpuinfo_dynamic[i].error), hdr, NULL))) {

                log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(gpuinfo_static)");
                quickpool_errno = ERROR_XDR;
                return FALSE;
            }
        }
    }

    return TRUE;
} // end function xdr_host_info

/**
 * @brief       XDR: xdr function to exchange single node load.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   hostload        #2: single node load to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
static bool_t
xdr_host_load(XDR *xdrs, void *hostload, struct header *hdr, void *argument)
{
    struct QuickPoolHostLoad *load = (struct QuickPoolHostLoad *)hostload;
    unsigned int *nIndicies = (unsigned int *)argument;
    unsigned int i;
    if (XDR_FREE == xdrs->x_op) {

        FREEUP(load->host_name);
        FREEUP(load->status);
        FREEUP(load->load_values);
        if (load->gpu_load) {
            FREEUP(load->gpu_load->avail_gpu_mem);
            FREEUP(load->gpu_load->gpu_mode);
            FREEUP(load->gpu_load->gpu_ut);
            for (i = 0; i < load->gpu_load->num_GPU; i++) {
                FREEUP(load->gpu_load->status[i]);
            }
            FREEUP(load->gpu_load->status);
            FREEUP(load->gpu_load->gpu_temperature);
            FREEUP(load->gpu_load->gpu_id);
        }
        FREEUP(load->gpu_load);

        return TRUE;
    }

    if (!gf_xdr_string(xdrs, &load->host_name, hdr, NULL)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(host_name)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < *nIndicies) {

        load->status = (int *)calloc(1+GET_INTNUM(*nIndicies), sizeof(int));
        load->load_values = (double *)calloc(*nIndicies, sizeof(double));
        if (NULL == load->status || NULL == load->load_values) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        *nIndicies*(sizeof(int)+sizeof(double)));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }


    for (i=0; i<1+GET_INTNUM(*nIndicies); i++) {

        if (!xdr_int(xdrs, (int *) &load->status[i])) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_int(status)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    for (i=0; i<*nIndicies; i++) {

        if (!xdr_double(xdrs, &load->load_values[i])) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_double(load_values)", i);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    int gpuFlag = FALSE;
    if (XDR_ENCODE == xdrs->x_op && NULL != load->gpu_load) {
        gpuFlag = TRUE;
    }

    if (!xdr_int(xdrs, &gpuFlag)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(gpu flag)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!gpuFlag) { // no gpu information for encode/decode.
        return TRUE;
    }

    if (XDR_DECODE == xdrs->x_op) {

        load->gpu_load = (struct QuickPoolHostGPUload *)calloc(1, sizeof(struct QuickPoolHostGPUload));
        if (NULL == load->gpu_load) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        sizeof(struct QuickPoolHostGPUload));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    if (!xdr_u_int(xdrs, &load->gpu_load->num_GPU)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_GPU)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }    

    if (XDR_DECODE == xdrs->x_op && 0 < load->gpu_load->num_GPU) {

        load->gpu_load->avail_gpu_mem = (double *)calloc(load->gpu_load->num_GPU, sizeof(double));
        load->gpu_load->gpu_mode = (int *)calloc(load->gpu_load->num_GPU, sizeof(int));
        load->gpu_load->status = (char **)calloc(load->gpu_load->num_GPU, sizeof(char *));
        load->gpu_load->gpu_id = (int *)calloc(load->gpu_load->num_GPU, sizeof(int));
        load->gpu_load->gpu_temperature = (int *)calloc(load->gpu_load->num_GPU, sizeof(int));
        load->gpu_load->gpu_ut = (float *)calloc(load->gpu_load->num_GPU, sizeof(float));
        if (NULL == load->gpu_load->avail_gpu_mem || NULL == load->gpu_load->gpu_mode
            || NULL == load->gpu_load->gpu_temperature || NULL == load->gpu_load->gpu_ut) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        load->gpu_load->num_GPU*2*(sizeof(double)+sizeof(int)));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    unsigned int j;        
    for (j = 0; j < load->gpu_load->num_GPU; j++) {
        if(!(xdr_double(xdrs, &load->gpu_load->avail_gpu_mem[j])
             && xdr_float(xdrs, &load->gpu_load->gpu_ut[j])
             && gf_xdr_string(xdrs, &(load->gpu_load->status[j]), hdr, NULL)
             && xdr_int(xdrs, &load->gpu_load->gpu_id[j])
             && xdr_int(xdrs, &load->gpu_load->gpu_mode[j])
             && xdr_int(xdrs, &load->gpu_load->gpu_temperature[j]))) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_double(gpu load)", j);
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }    

    return TRUE;
} // end function xdr_host_load

/**
 * @brief       XDR: xdr function to exchange single user group.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   groupinfo       #2: single user group to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
xdr_usergroup_info(XDR *xdrs, void *groupinfo, struct header *hdr, void *argument)
{
    struct QuickPoolUserGroupInfo *info = (struct QuickPoolUserGroupInfo *)groupinfo;

    if (XDR_FREE == xdrs->x_op) {

        FREEUP(info->group_name);
        free_namelist(info->member_list);
        info->member_list = NULL;
        FREEUP(info->user_shares);
        FREEUP(info->exclude_members);
        return TRUE;
    }

    if (XDR_DECODE == xdrs->x_op) {

        info->member_list = (struct nameList *)calloc(1, sizeof(struct nameList));
        if (NULL == info->member_list) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        sizeof(struct nameList));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    if (!(gf_xdr_string(xdrs, &(info->group_name), hdr, NULL)
          && gf_xdr_string(xdrs, &(info->user_shares), hdr, NULL)
          && gf_xdr_string(xdrs, &(info->exclude_members), hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(group_name)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!xdr_u_int(xdrs, &info->member_list->num_name)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_name)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < info->member_list->num_name) {

        info->member_list->names = (char **)calloc(info->member_list->num_name, sizeof(char *));
        if (NULL == info->member_list->names) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        info->member_list->num_name*sizeof(char*));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    unsigned int i;
    for (i=0; i<info->member_list->num_name; i++) {

        if (!(gf_xdr_string(xdrs, &(info->member_list->names[i]), hdr, NULL))) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__,
                        "gf_xdr_string(names)", i);
            info->member_list->num_name = i;
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    return TRUE;
} // end function xdr_usergroup_info

/**
 * @brief       XDR: xdr function to exchange single host group.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   groupinfo       #2: single host group to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
xdr_hostgroup_info(XDR *xdrs, void *groupinfo, struct header *hdr, void *argument)
{
    struct QuickPoolHostGroupInfo *info = (struct QuickPoolHostGroupInfo *)groupinfo;

    if (XDR_FREE == xdrs->x_op) {

        FREEUP(info->group_name);
        free_namelist(info->member_list);
        info->member_list = NULL;
        FREEUP(info->exclude_members);

        return TRUE;
    }

    if (XDR_DECODE == xdrs->x_op) {

        info->member_list = (struct nameList *)calloc(1, sizeof(struct nameList));
        if (NULL == info->member_list) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        sizeof(struct nameList));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    if (!(gf_xdr_string(xdrs, &(info->group_name), hdr, NULL)
          && gf_xdr_string(xdrs, &(info->exclude_members), hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(group_name)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!xdr_u_int(xdrs, &info->max_slots)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(max_slots)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!xdr_u_int(xdrs, &info->member_list->num_name)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_name)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < info->member_list->num_name) {

        info->member_list->names = (char **)calloc(info->member_list->num_name, sizeof(char *));
        if (NULL == info->member_list->names) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        info->member_list->num_name*sizeof(char*));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    unsigned int i;
    for (i=0; i<info->member_list->num_name; i++) {

        if (!(gf_xdr_string(xdrs, &(info->member_list->names[i]), hdr, NULL))) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__,
                        "gf_xdr_string(names)", i);
            info->member_list->num_name = i;
            quickpool_errno = ERROR_XDR;
            return FALSE;
        }
    }

    return TRUE;
} // end function xdr_hostgroup_info

/**
 * @brief       XDR: xdr function to exchange single user information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   userinfo        #2: single user information to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
xdr_user_info(XDR *xdrs, void *userinfo, struct header *hdr, void *argument)
{
    struct QuickPoolUserInfo *info = (struct QuickPoolUserInfo *)userinfo;

    if (XDR_FREE == xdrs->x_op) {

        if (NULL == info) {
            return TRUE;
        }

        FREEUP(info->user);

        return TRUE;
    }

    if (!(gf_xdr_string(xdrs, &info->user, hdr, NULL)
          && xdr_u_int(xdrs, &info->max_num_slot))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(user)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(xdr_u_int(xdrs, &info->num_job_slot) && xdr_u_int(xdrs, &info->num_pending_slot)
          && xdr_u_int(xdrs, &info->num_running_slot) && xdr_u_int(xdrs, &info->num_SSUSP_slot)
          && xdr_u_int(xdrs, &info->num_USUSP_slot) && xdr_u_int(xdrs, &info->num_reserving_slot))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_slot)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    return TRUE;
} // end function xdr_user_info

/**
 * @brief       XDR: xdr function to exchange job array header.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   jobinfo         #2: job array header to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
xdr_jobinfo_array(XDR *xdrs, void *jobinfo, struct header *hdr, void *argument)
{
    struct QuickPoolJobInfo *info = (struct QuickPoolJobInfo *)jobinfo;

    if (XDR_FREE == xdrs->x_op) {

        FREEUP(info->submit->dependency);
        FREEUP(info->submit->job_name);

        return (TRUE);
    }

    if (!xdr_jobID(xdrs, (void *)&(info->jobid), hdr, argument)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_jobID");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(xdr_int(xdrs, &(info->status)) && xdr_int(xdrs, &(info->reason_id))
          && xdr_int(xdrs, &(info->reason_detail))
          && xdr_long(xdrs, &(info->start_time))
          && xdr_long(xdrs, &(info->possible_start))
          && xdr_long(xdrs, &(info->end_time))
          && xdr_float(xdrs, &(info->used_cpu_time))
          && xdr_u_int(xdrs, &(info->num_execute_node)))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(status and so on)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!(gf_xdr_string(xdrs, &(info->submit->dependency), hdr, NULL)
          && xdr_long(xdrs, &(info->submit->submit_time))
          && gf_xdr_string(xdrs, &(info->submit->job_name), hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(dependency and so on)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    return TRUE;
} // end function xdr_jobinfo_array

/**
 * @brief       XDR: xdr function to exchange single job group information.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   jobgroup        #2: single job group to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
static bool_t
xdr_jobgroup(XDR *xdrs, void *jobgroup, struct header *hdr, void *argument)
{
    struct QuickPoolJobGroup *group = (struct QuickPoolJobGroup *)jobgroup;

    if (XDR_FREE == xdrs->x_op) {

        if (NULL == group) {
            return TRUE;
        }

        FREEUP(group->path);
        FREEUP(group->name);

        return TRUE;
    }

    if (!(gf_xdr_string(xdrs, &(group->path), hdr, NULL)
          && gf_xdr_string(xdrs, &(group->name), hdr, NULL))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(path)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    unsigned int i;
    for (i = 0; i < NUM_JGRP_COUNTERS; i++) {

        if (!xdr_int(xdrs, &(group->counts[i]))) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__, "xdr_int(counts)", i);
            return FALSE;
        }
    }

    if (!xdr_int(xdrs, &group->max_jobs)) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(max_jobs)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    return TRUE;
} // end function xdr_jobgroup

/**
 * @brief       XDR: xdr function to exchange single job message.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   jobmsg          #2: single job message to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
static bool_t
xdr_jobmsg(XDR *xdrs, void *jobmsg, struct header *hdr, void *argument)
{
    struct QuickPoolJobMsg *message = (struct QuickPoolJobMsg *)jobmsg;

    if (XDR_FREE == xdrs->x_op) {

        if (NULL == message) {
            return TRUE;
        }

        FREEUP(message->message);
    }

    if (!xdr_u_long(xdrs, (unsigned long *)&message->post_time)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_long(post_time)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    if (!gf_xdr_string(xdrs, &message->message, hdr, argument)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(message)");
        quickpool_errno = ERROR_XDR;
        return FALSE;
    }

    return TRUE;
} // end function xdr_jobmsg

/**
 * @brief       XDR: xdr function to exchange single job dependency.
 *
 * @param[in|out]   xdrs            #1: xdrs for exchanging data
 * @param[in|out]   jobdep          #2: single job dependency to be exchanged
 * @param[in]       hdr             #3: XDR header
 * @param[in|out]   argument        #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
xdr_jobdep(XDR *xdrs, void *jobdep, struct header *hdr, void *argument)
{
    struct QuickPoolJobDep *dep = (struct QuickPoolJobDep *)jobdep;

    if (XDR_FREE == xdrs->x_op) {

        if (NULL == dep) {
            return TRUE;
        }

        FREEUP(dep->dependency);
        FREEUP(dep->jobid);

        return TRUE;
    }

    if (!(gf_xdr_string(xdrs, &dep->dependency, hdr, argument)
          && gf_xdr_string(xdrs, &dep->jobid, hdr, argument)
          && xdr_int(xdrs, &dep->jstatus) && xdr_int(xdrs, &dep->depstatus))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(dependency)");
        quickpool_errno = ERROR_XDR;

        return FALSE;
    }

    return TRUE;
} // end function xdr_jobdep
